Wednesday, October 8, 2014

Shift Registers

AIM

As I promised in the last posts, I'm testing the potential of shift registers. In the experiments so far, the number of devices (switches, led, etc...) we could control was limited to the number of pins of the Arduino board. Using shift registers we can control unlimited devices, using only three pins. Like usual, I'm building a graphical interface with LabView and I'm using XBee radio transmitters.


SHIFT REGISTER 74HC595

One of the Arduino pins sends a serial binary string (0 and 1). This string is recorded in the register and it's sent to the outputs of the registers. For example if the serial string from the arduino is "00101100" (8 bit), the output pins of the register will be:
  1: off
  2: off
  3: on
  4: off
  5: on
  6: on
  7: off
  8: off

Picture from www.adafruit.com

One shift register can handle 8 bits, but we can chain them together to control more devices. In this case I'm controlling 32 LEDs, so I need 4 shift registers. A chain of registers works exactly as one register. They need a data pin (where the serial string is sent to) a clock and latch. Every time the clock pin goes from low to high, the status of the data pin is recorded. When the latch pin gets low, the recorded data is sent to the 8 output pins. If you have more than one register, you can keep sending this data to the register, and after the 8th bit it keeps going to the next register. When you set the latch low, all the registers send the recorded data to the output pins. To chain shift registers they have to share clock (pin 11, blue wire) and latch (pin 12, purple wire). The output data pin of each register (pin 9) is connected to the input data pin (pin 14) of the next one. Obviously the last register is not using the output data pin. The shift register also needs connection to power (5V) and ground.


That's how I wired them up:



And this is how it looks:




LABVIEW

The idea of this control panel is similar to the other experiments, just with more items to control.


In this case each block of 8 switches (blue, yellow, red and green) is creating a byte as in the 8 switches experiment. The bytes are then converted to strings and concatenated together, separated by commas. 

In the diagram you can see the first block of switches and lights (blue). The pink lines coming from the bottom are the strings from the other three blocks (yellow, red and green).
The delay is necessary not to overflow the buffer of the Arduino serial port.

SKETCH

The Arduino IDE includes a useful command: shiftOut(). It writes a byte in sequence of 8 bits, while switching the clock 8 times. I'm using 4 shift registers, so I have to use that command 4 times before I switch LATCH to low (so the registers set their output pins). The values from the wireless serial string is read as an integer with the command parseInt(), but it's used as a byte by the function shiftOut().


int bval;
int yval;
int rval;
int gval;

const int SER =8; //Serial output to shift register
const int LATCH =9; //Shift register latch pin
const int CLK =10; //Shift register clock pin

void setup()
{
  Serial.begin(9600);
  pinMode(SER, OUTPUT);
  pinMode(LATCH, OUTPUT);
  pinMode(CLK, OUTPUT);
}

void loop()
{
  if(Serial.available() > 0)
  {
  gval = Serial.parseInt();
  rval = Serial.parseInt();
  yval = Serial.parseInt();
  bval = Serial.parseInt();

    digitalWrite(LATCH, LOW); //Latch low
    shiftOut(SER, CLK, MSBFIRST, bval);
    shiftOut(SER, CLK, MSBFIRST, yval);
    shiftOut(SER, CLK, MSBFIRST, rval);
    shiftOut(SER, CLK, MSBFIRST, gval);
    digitalWrite(LATCH, HIGH);
  }
}

CONCLUSIONS

Shift registers are very useful and easy to use, thanks to the Arduino library. We can control hundreds of LEDs or other devices using only 3 pins of the Arduino board.


REFERENCES

Exploring Arduino by Jeremy Blum (Chapter 7 - Shift Registers)


Saturday, October 4, 2014

Real Time Clock

AIM

I fixed one of the limits of my datalogger: the Arduino doesn't know what time it is. I just bought this DS1307 RTC (Real Time Clock) for a dollar, to add the function of time to my recordings. The DS1307 has an integrated I2C interface which makes it easy to communicate date and time using strings. It also has its own library to control the clock with easy commands. In this experiment I just added the clock function to my datalogger experiment, so I can see date and time for each data record.





SKETCH

This code is a copy of the datalogger project, plus the commands of the RTC. For the RTC I'm referring to the book "exploring arduino" from Jeremy Blum. I found it very useful and I recommend you to buy it. It covers basic to advanced topics, including practical projects, and it explains about electronics and useful components, not only Arduino. You can download the RTClib.h library here. Note that it's in a folder named "RTClib-master", which can't be read by the Arduino IDE. You have to rename it without "-" symbol.
As you can see, in the setup loop the code says "if the clock is not running write date and time from computer". Then the clock starts running. In the loop we extract the data we want from the string (year, month, day, hour, minute, seconds) and we set the format of date and time. These strings are then added to the string recorded to the SD card in the file "datalogger.log", separated by a tab ("\t").


#include <DHT11.h>
#include <SD.h>
#include <Wire.h> //For RTC
#include "RTClib.h" //For RTC

int pin=3;
DHT11 dht11(pin); 

RTC_DS1307 RTC;
String year, month, day, hour, minute, second, time, date;

const int chipSelect = 10;

void setup()
{
  pinMode(10, OUTPUT);
  
  if (!SD.begin(chipSelect)) {
    return;
  }
Wire.begin();
RTC.begin();
if (! RTC.isrunning())
{
RTC.adjust(DateTime(__DATE__, __TIME__));
}
}

void loop()
{
  DateTime datetime = RTC.now();
  year = String(datetime.year(), DEC);
  month = String(datetime.month(), DEC);
  day = String(datetime.day(), DEC);
  hour = String(datetime.hour(), DEC);
  minute = String(datetime.minute(), DEC);
  second = String(datetime.second(), DEC);
  date = year + "/" + month + "/" + day;
  time = hour + ":" + minute + ":" + second;
  
  int err;
  float temp, humi;
  if((err=dht11.read(humi, temp))==0)
  {
  int t,h;
  t = (int) temp;
  h = (int) humi;
  String dataString = "";
    dataString += date;
    dataString += "\t";
    dataString += time;
    dataString += "\t";
    dataString += "temperature:";
    dataString += String(t);
    dataString += "\t";
    dataString += "humidity:";
    dataString += String(h);
    dataString += "\t";
    dataString += "light:";
    dataString += String(analogRead(0));
    
  File dataFile = SD.open("datalog.log", FILE_WRITE);
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
  }
  }
  delay(3000);
}

CONCLUSIONS

This is how the data is recorded to the datalog.log file in the SD card: