The Arduino Uno is a wonderfully versatile and cheap ATmega-based prototyping board, here it's tasked it to perform the primary functions of an NI-DAQ which costs a considerable amount more. The Arduino doesn't have fantastic specifications, but it can be easily coupled to other IC's that meet most requirements.

In the picture below a nibble is fed from one of the Ardunio's I/O ports to, perhaps, the world's smallest fully-featured oscilloscope (Xmega based):


The code loaded on the ATmega's EEPROM is shown at the bottom of this page and it allows for external inputs to control the behaviour of the board. This is controlled with Labview via a USB cable that is also providing power for both the Arduino and the oscilloscope. Labview examples for controlling the digital output ports... 


...and the six-analogue input channels are available at the bottom of this page. Simple as that.


Arduino code:

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif

#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif // defines cbi and sbi so we can change ADC prescalers

byte rbyt[16]; // read byte stream
byte i = 0; // looping variable 1
boolean nc = false; // /n deliminated command found
boolean ar = 0; // read flags for analogue channels
long adelay = 10; // delay between analogue readings, ms
unsigned long ttime; // target analogue read time


void setup() {
  Serial.begin(115200); // let's talk at high speed
  sbi(ADCSRA,ADPS2);
  cbi(ADCSRA,ADPS1);
  cbi(ADCSRA,ADPS0); // change prescaler to 16, allowing ADC to settle in 16us
}

void loop() {
  
  if (Serial.available() > 0) { // check for bytes waiting on the stream
  
   rbyt[i] = Serial.read(); // if so add to stream
   
   if (rbyt[i] == 10) // /n indicates the end of a command
   {
      nc = true;
      i = 0; // reset stream pointer
   }
   else
   {
     i++;
   }
    
   if (i >= 15) {
     i = 0;
     Serial.println("cmd_err"); // if stream > 16 bytes report an error
    }
  }
  
    if (!nc & (millis() > ttime)){
      ttime += adelay;
      if ((ar & B1) > 0){        
        // delay(10);
        Serial.print("A0=");
        Serial.print(analogRead(0));
        Serial.print(",");
        Serial.println(millis());
      }
      if ((ar & B10) > 0){
        // delay(10);
        Serial.print("A1=");
        Serial.print(analogRead(1));
        Serial.print(",");
        Serial.println(millis());
      }
      if ((ar & B100) > 0){
        // delay(10);
        Serial.print("A2=");
        Serial.print(analogRead(2));
        Serial.print(",");
        Serial.println(millis());
      }
      if ((ar & B1000) > 0){
        // delay(10);
        Serial.print("A3=");
        Serial.print(analogRead(3));
        Serial.print(",");
        Serial.println(millis());
      }
      if ((ar & B10000) > 0){
        // delay(10);
        Serial.print("A4=");
        Serial.print(analogRead(4));
        Serial.print(",");
        Serial.println(millis());
      }
      if ((ar & B100000) > 0){
        // delay(10);
        Serial.print("A5=");
        Serial.print(analogRead(5));
        Serial.print(",");
        Serial.println(millis());
      }
    }
  
  if (nc) {
    while(rbyt[i] != 10){
      Serial.print(rbyt[i], BYTE);
      i++;
    }
    switch (rbyt[0]) {
      
      case 65: // Axx read analogue channel
      ar = rbyt[1] >> 2;
      adelay = sq(rbyt[2] - 11)*10; // ignore bit values 0-10
      ttime = millis() + 10; // 10ms delay to separate comms
      break;
      
      case 68: // Dxx program/read digital port
       switch (rbyt[1]) {
         case 79: // DOx set bit x as output
          pinMode(rbyt[2] - 48, OUTPUT);
         break;
         case 73: // DIx set bit x as input
          pinMode(rbyt[2] - 48, INPUT);
         break;
         case 87: // DWx1|0 write 1|0 to bit x (set output first!) 
          if (rbyt[3] == '1')
          {
            digitalWrite(rbyt[2] - 48, HIGH);
          }
          else
          {
            digitalWrite(rbyt[2] - 48, LOW);
          }
          break;
       }
       break;
       
      case 66: // BxD|Wy byte operation to port x 
       switch (rbyt[1]) {
        case 68: // BD
        switch (rbyt[2]) {
          case 68: // BDD
          rbyt[3] = rbyt[3] & B11111100; // let's not change Rx & Tx on port D
          DDRD = DDRD | rbyt[3];
          break;
          case 87: // BDW
          rbyt[3] = rbyt[3] & B11111100;
          PORTD = rbyt[3];
          break;
          } 
         break;
          case 66: // BB
          switch (rbyt[2]) {
            case 68: // BBD
            rbyt[3] = rbyt[3] >> 2; // only 6 bits on B, sent << 2 to avoid \n
            DDRB = DDRB | rbyt[3];
            break;
            case 87: // BBW
            rbyt[3] = rbyt[3] >> 2;
            PORTB = rbyt[3];
            break;
          }
          break;
        }
        break;
     }
    i = 0;
    nc = false;
  }                   
}

Č
ċ
ď
ain_demo.zip
(50k)
Rob Young,
Jan 17, 2011, 7:32 AM
ċ
ď
dout_demobitbybit.zip
(28k)
Rob Young,
Jan 17, 2011, 7:32 AM
ċ
ď
dout_demobytebybyte.zip
(30k)
Rob Young,
Jan 17, 2011, 7:32 AM