Skip to main content
Version: current

Arduino UNO

Description

The Arduino UNO interface equipment type is a way of using the Arduino UNO as a control system and/or data logger with SAFE. This can be used for simple control of LEDs, 5 volt inputs and much. It can also be used for simple data logging using the digital and analog pins. To use the Arduino UNO you are only required to upload some specific code letting SAFE communicate with the Arduino UNO over the serial interface. Find the Arduino UNO code you need to copy in the bottom of this page.

arduinoUNO

Attributes

AttributeValue
Name
Manufacturer
Model
Serial Number
Internal Number
COM PORTCOM1
Baud Rate115200
Sample Rate1
Channels (IN)18
Channels (OUT)12

Name

Name specifies the name of the block. It will automatically be given the name of the device.

Manufacturer

Manufacturer is an optional specification you can write.

Model

Model is an optional specification you can write.

Serial Number

Serial Number is an optional specification you can write.

Internal Number

Internal Number is an optional specification you can write.

COM Port

COM Port is the communication port that the Arduino UNO is connected to your computer on. The default is COM1, to see what your port the device is connected on, go to device manager and find it.

Baud Rate

Baud Rate is the rate at which information is transferred. It is default 115200 for our Arduino Code but can be set to anything as long as the Baud Rate in the Arduino code and in SAFE are identical.

Sample Rate

Sample Rate is how many times the device samples per second given in Hertz (Hz). Default is 1 Hz but it can be set to what you want. It is stronly recommended that it is set to between 0.1 Hz and 20 Hz. REMEMBER that the sample rate in SAFE and fs in the Arduino code MUST match.

Channels (IN)

Channels (IN) contains the 18 usable input channel available on Arduino UNO including analog inputs and digital inputs.

For each digital input you can choose the Pin Mode to be either INPUT or INPUT_PULLUP.

For each analog input you can specify the sensitivity which default is 204.6 FS per Volt.

Channels (OUT)

Channels (OUT) contains the 12 usable output channel available on the Arduino UNO. There are no specific output channel settings

Arduino UNO Code

In order to test with the Arduino in SAFE you must upload the following code to the Arduino UNO using the Arduino IDE

In the code you can set fs to your desired fs as long as it is identical to the Sample Rate of the Arduino on the Configuration board. If you need a digital output you must define it in the Arduino code. Default the are commented in the code. So uncomment the pinMode of the pin you want as an output.

int pinVal = 0;

// define the ports
int digital_ports [] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
int analog_inputs [] = {0, 1, 2, 3, 4, 5};

// char array for serial input data
const byte numChars = 45;
char receivedChars[numChars];
boolean newData = false;

// variables for sampling
String writeString;
boolean do_sample = false;
unsigned long timeBetweenSamples = 0;
unsigned long loopEndTime = 0;
unsigned long loopStartTime = 0;

/****************************************************
   Define the sample rate
   Range: 0.1 < fs < 20
 ****************************************************/
float fs = 1;
int delay_ms = 0;

#define UNKNOWN_PIN 0xFF

void setup() {
  Serial.begin(115200);

  /****************************************************
     Define digital pinmodes, if different from INPUT
   ****************************************************/
  //pinMode(2, OUTPUT);
  //pinMode(3, OUTPUT);
  //pinMode(4, OUTPUT);
  //pinMode(5, OUTPUT);
  //pinMode(6, OUTPUT);
  //pinMode(7, OUTPUT);
  //pinMode(8, OUTPUT);
  //pinMode(9, OUTPUT);
  //pinMode(10, OUTPUT);
  //pinMode(11, OUTPUT);
  //pinMode(12, OUTPUT);
  //pinMode(13, OUTPUT);

  delay_ms = (1 / fs) * 1000;

}

void loop() {
  loopStartTime = millis();

  // sample input values and transmit to serial
  if (do_sample == true) {
    // Write pinstates to PC
    for (int pin : digital_ports) {  // if channel is input
      if (getPinMode(pin) == INPUT || getPinMode(pin) == INPUT_PULLUP) {
        pinVal = digitalRead(pin);
        writeString += String(pinVal) + ":";
      }
      else {  // add -1 if channel is not active as an input
        writeString += "-1:";
      }
    }
    for (int pin : analog_inputs) {
      pinVal = analogRead(pin);
      writeString += String(pinVal) + ":";
    }
    writeString.remove(writeString.length() - 1, 1);
    Serial.println(writeString);
    writeString = "";
    do_sample = false;
  }

  // read output states from serial and set them
  recvWithStartEndMarkers();
  if (newData == true) {  // if all the new data has arrived
    int idx = 0;
    for (int pin : digital_ports) {
      if (getPinMode(pin) == OUTPUT) {  // if pin is output
        pinVal = receivedChars[idx] - '0';  // convert char array value to int
        if (pinVal == 0 || pinVal == 1) {
          digitalWrite(pin, pinVal);
        }
      }
      idx = idx + 1;
    }
    newData = false;
  }

  delay(1);
  loopEndTime = millis();

  // check sample time
  if (do_sample == false) {
    timeBetweenSamples = timeBetweenSamples + (loopEndTime - loopStartTime);

    if (timeBetweenSamples >= delay_ms) {
      do_sample = true;
      timeBetweenSamples = 0;
    }
  }
}


uint8_t getPinMode(uint8_t pin)
// Function to get pinMode on a specific pin
{
  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);

  // I don't see an option for mega to return this, but whatever...
  if (NOT_A_PIN == port) return UNKNOWN_PIN;

  // Is there a bit we can check?
  if (0 == bit) return UNKNOWN_PIN;

  // Is there only a single bit set?
  if (bit & bit - 1) return UNKNOWN_PIN;

  volatile uint8_t *reg, *out;
  reg = portModeRegister(port);
  out = portOutputRegister(port);

  if (*reg & bit)
    return OUTPUT;
  else if (*out & bit)
    return INPUT_PULLUP;
  else
    return INPUT;
}

boolean recvWithStartEndMarkers() {
  // function that reads serial input between to marker characters
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;
  boolean read_something = false;

  while (Serial.available() > 0 && newData == false) {
    rc = Serial.read();
    read_something = true;

    if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }
    else if (rc == startMarker) {
      recvInProgress = true;
    }
  }
  return read_something;
}