Với bo mạch Arduino UNO đơn giản, chúng ta có thể ứng dụng và biến nó thành một thiết bị hổ trợ đo đạt và phân tích. Hổ trợ rất nhiều trong công cuộc nghiên cứu.. ngâm và cứu được .
CKD giới thiệu dự án mở (open source) XOscillo cho các bạn thích tìm tòi nghiên cứu với chi phí rất thấp .
Với chi phí khoảng dưới 200K (board Arduino khoảng 150K và vài linh kiện điện tử khác khoảng dưới 50K) hoặc có thể ít hơn nếu tận dụng các board Arduino có sẵn cũng như các linh kiện tận dụng. Bằng cách kết hợp máy tính với Arduino, chúng ta có thể chế tạo được thiết bị do và phân tích tích hiệu như "Máy hiện sóng" (oscilloscope) hay máy phân tích logic (logic analyzer).
Link gốc XOscillo - A software oscilloscope that acquires data using an arduino or a parallax (more platforms to come).
Các bạn có thể tìm hiểu thêm nhiều thông tin liên quan với link trên
Vài hình ảnh:
- XOscillo phân tích tín hiệu tương tự (analog)
- XOscillo phân tích tín hiệu số (digital/logic analyzer)
- Tần số max: 7kHz.
- Số kênh analog: 4 kênh (tần số lấy mẫu khi này là 7/4 kHz).
- Độ phân giải (tạo sóng) 8bit (256)
- Độ phân giải ADC 10bit (1024)
- Ngưỡng đo: 0-5V
- Trigger trên kênh 0.
Do Arduino giới hạn về tốc độ làm việc, tốc độ truyền do đó.. các dự án phát triển trên nền arduino đều bị giới hạn này. XOscillo cũng không ngoại lệ, tần số lấy mẫu khá thấp.
Mã:
// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
//
// pins assignment
//
#define BUILTINLED 13
#define PWM_GENERATOR 11
#define ledPin 13 // LED connected to digital pin 13
//
// globals
//
unsigned char triggerVoltage = 0;
unsigned char lastADC = 0;
unsigned char triggered = 0;
unsigned int DataRemaining = 1500;
unsigned char channel=0;
unsigned char numChannels=1;
unsigned char channels[4];
//
// Commands
//
#define CMD_IDLE 0
#define CMD_RESET 175
#define CMD_PING '?'
#define CMD_READ_ADC_TRACE 170
#define CMD_READ_BIN_TRACE 171
void StartAnalogRead(uint8_t pin)
{
// set the analog reference (high two bits of ADMUX) and select the
// channel (low 4 bits). this also sets ADLAR (left-adjust result)
// to 0 (the default).
ADMUX = (DEFAULT << 6) | (pin & 0x07);
ADMUX |= _BV(ADLAR);
#if defined(__AVR_ATmega1280__)
// the MUX5 bit of ADCSRB selects whether we're reading from channels
// 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high).
ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
#endif
// without a delay, we seem to read from the wrong channel
//delay(1);
// start the conversion
sbi(ADCSRA, ADSC);
}
uint8_t EndAnalogRead()
{
uint8_t low, high;
// ADSC is cleared when the conversion finishes
while (bit_is_set(ADCSRA, ADSC));
// we have to read ADCL first; doing so locks both ADCL
// and ADCH until ADCH is read. reading ADCL second would
// cause the results of each conversion to be discarded,
// as ADCL and ADCH would be locked when it completed.
uint8_t result = ADCH;
return result;
}
void setup()
{
// set prescale to 16
sbi(ADCSRA,ADPS2) ;
cbi(ADCSRA,ADPS1) ;
cbi(ADCSRA,ADPS0) ;
pinMode( PWM_GENERATOR, OUTPUT );
analogWrite(PWM_GENERATOR, 128);
pinMode( 4, OUTPUT );
pinMode( 5, OUTPUT );
digitalWrite(4, HIGH);
digitalWrite(5, LOW);
//Serial.begin(115200);
Serial.begin(1000000);
for(int i=2;i<8;i++)
{
pinMode(i, INPUT); // sets the digital pin 7 as input
digitalWrite(i, LOW);
}
// Serial.begin(1000000);
// Serial.begin(153600);
// Serial.begin(9600);
}
unsigned char command = 0;
void ProcessSerialCommand( byte in )
{
if ( in == CMD_PING )
{
Serial.write( 79 ) ;
Serial.write( 67 ) ;
Serial.write( triggerVoltage ) ;
Serial.write( DataRemaining>>8 ) ;
Serial.write( DataRemaining&0xff ) ;
for (int i=0;i<2;i++)
{
Serial.write( triggerVoltage ) ;
}
}
else if ( in == CMD_RESET )
{
command = CMD_IDLE;
Serial.write( "OK" ) ;
digitalWrite(ledPin, LOW);
}
else if ( in == CMD_READ_ADC_TRACE )
{
while( Serial.available() < 9);
triggerVoltage = Serial.read();
DataRemaining = Serial.read()<<8;
DataRemaining |= Serial.read();
numChannels = Serial.read();
for (int i=0;i<4;i++)
{
channels[i] = Serial.read();
}
analogWrite(PWM_GENERATOR, Serial.read());
Serial.write( 85 );
triggered = 0;
//get a fresher value for lastADC
channel = 0;
StartAnalogRead(channels[channel]);
lastADC = EndAnalogRead();
digitalWrite(ledPin, HIGH);
command = CMD_READ_ADC_TRACE;
}
else if ( in == CMD_READ_BIN_TRACE )
{
while( Serial.available() < 3);
triggerVoltage = Serial.read();
DataRemaining = Serial.read()<<8;
DataRemaining |= Serial.read();
analogWrite(9, 64);
analogWrite(10, 128);
analogWrite(11, 192);
triggered = 0;
digitalWrite(ledPin, HIGH);
command = CMD_READ_BIN_TRACE;
Serial.write( 85 );
}
}
void loop()
{
if (Serial.available() > 0)
{
ProcessSerialCommand( Serial.read() );
}
if ( command == CMD_READ_ADC_TRACE )
{
unsigned char v = EndAnalogRead();
if ( triggered == 0 )
{
if ( ((v >= triggerVoltage) && ( lastADC < triggerVoltage )) || (triggerVoltage == 0) )
{
triggered = 1;
digitalWrite(ledPin, LOW);
}
else
{
lastADC = v;
StartAnalogRead(channels[channel]);
return;
}
}
channel++;
if ( channel == numChannels )
{
channel=0;
DataRemaining--;
if ( DataRemaining == 0 )
{
command = CMD_IDLE;
}
}
Serial.write(v);
StartAnalogRead(channels[channel]);
}
else if ( command == CMD_READ_BIN_TRACE )
{
unsigned char v = PIND>>2; // remove tx/rx lines
Serial.write(v);
DataRemaining--;
if ( DataRemaining == 0 )
{
command = CMD_IDLE;
}
}
}
Tham khảo thêm giải pháp đo & phân tích dữ liệu khác:
- http://forum.cncprovn.com/threads/31...en-cuu-tai-gia