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:


Sunday, September 28, 2014

Wireless RGB LED and speaker control

AIM

Like the previous experiment, I want to send data from my computer to the Arduino to control a device, using radio frequencies. I'm using XBee transmitters for wireless communication. My model is XBee PRO S2: it uses 2.4GHz frequency at 50mW power, able to reach 3 km on open air. The configuration I'm using is always the same: AT mode, one coordinator (connected to the Arduino) and one router (connected to my computer). The purpose of the experiment is to change the colors of an RGB LED, and the volume and tune of a speaker, using a LabView graphical interface. This is different from the previous project because I need to send analog data now, so one byte is not enough. This time I need to send a string of values. The Arduino IDE includes a very useful command: Serial.parseInt() extract an integer number from a serial string.


ANALOG VOLTAGE

The arduino has some pins that can be used to output an analog voltage with 1023 increments from 0 to 5 V. This is not completely true: the 5 V pins are switched on and off at very high frequency so the average voltage changes. This works well in case of an LED because the human eyes can't see the LED going on and off hundred thousand times a second. What we see is the intensity of the light changing as a result of the time on and off. This tecnique is called PWM (pulse width modulation) and it works well also with motors. But in case of a speaker it's different. A speaker has to vibrate, which means that the power has to go an and off to produce sounds. The Arduino IDE has a function for that: tune() switches a pin on and off at a certain frequency to produce the sound we want in the speaker, always using the 5 V. 
As you can see in the following picture, the duty cycle (on/off time ratio) changes and the result average voltage (dotted line) changes as well. But the magnitude of the pulses doesn't change.
Picture from www.bristolwatch.com

This means that we can't use the PWM to control the volume. The only way to control the volume is to control the voltage of the pulses, using a potentiometer. But in this case I want to control everything from my LabView interface and that's why I'm using a Digital potentiometer (DigiPot). 

DIGIPOTS

DigiPots work as manual potentiometers, but they are IC (Integrated Circuits) controlled with digital signals. Some of them have an SPI communication interface like the MCP4231. The one I'm using is X9C103. It's controlled by 3 main pins: increment, up/down, chip select. The terminals of the variable resistance are High, Low, and Wiper, like in a normal potentiometer.

Picture from www.conrad.com

The digipot X9C103 has 99 increments of 101 Î© each for a maximum resistance of 10 kΩ. Plus the wiper has an internal resistance of 40 Î©. If we use the full scale in series with a speaker we find out that over the 1000 Î© it's really difficult to hear anything. For this reason I'm using only the first 10 increments, up to 1 kΩ. To do this, I made a scale from 0 to 10 in the labview interface and I add 90 in the Arduino sketch, so the resultant variable "vval" is between 90 and 100. I should have bought the digipot X9C102, which has a maximum resistance of 1 kΩ, so I would be able to use all 99 increments (of 10.1 Î© each).

WIRING

I spent many hours with this experiment rewiring the Digipot in different configuration but I only got it to work in this way: the Chip Select, Increment and Up/Down pins are controlled by the Arduino's pins 10, 11 and 12. The High terminal of the DigiPot is connected to pin 2 (the one we are going to "tune"), the Low is connected to ground, and the Wiper is connected to the positive of the speaker. The negative of the speaker is connected to ground. The DigiPot also needs a connection to 5V and ground.
The RGB LED is actually composed by 3 LEDs (red, green and blue) with common cathode (the negative terminal). Each LED needs a resistance: I'm using 220 Î© for the red and 330 Î© for the green and blue, because they have a different voltage drop. Pins 5,6 and 7 control the power to these LEDs (using PWM).
As usual, I connect an LCD screen to show me what's going on in the brain of the Arduino.


LABVIEW INTERFACE

This time it took me few minutes to create this simple page: the configuration of the VISA function for the serial communication is the same as in the previous project. Three colored bars control the intensity of the LEDs (0 to 255), and two horizontal bars control tune and volume of the speaker.


As you can see from the programming diagram, the numbers are converted to strings and then added together in an array, divided by commas. A delay is necessary not to overflow the buffer of the Arduino serial port.

SKETCH

I have rewritten this sketch many times before I got it to work.
After the serial string is read, the single values are extracted by the function parseInt(). The LED pins are set at these values straight away using PWM.
The X9C103 has its own library <DigiPotX9Cxxx.h> (download here) that allows us to use it easily. The variable "vval" (the wanted volume) is compared with the current volume and if it's different, the function pot.increase() and pot.decrease() adjust the value of the DigiPot.
The function "tune" has 2 arguments: the pin we want to tune and the value. This value can be seen in the file "pitches.h" included in the Arduino IDE. I didn't include this library because I'm not interested in playing particular notes, but I just wanna make some noise. Those values are between about 30 to 5000. I've chosen a range between 100 and 4000 to avoid acute or heavy noises.

#include <DigiPotX9Cxxx.h>
DigiPot pot(11,10,12);
#include <LiquidCrystal.h>
LiquidCrystal lcd(26, 27, 28, 29, 30, 31);

const int RED =7;
const int GREEN =6;
const int BLUE =5;

int rval = 0;
int gval = 0;
int bval = 0;
int tval = 0;
int vval = 0;
int currentvolume = 0;

void setup()
{
  pot.decrease(100);
  Serial.begin(9600);
  pinMode(RED, OUTPUT);
  pinMode(GREEN, OUTPUT);
  pinMode(BLUE, OUTPUT);
  lcd.begin(16, 2);
}
void loop()
{
  while (Serial.available() > 0)
  {
  rval = Serial.parseInt();
  gval = Serial.parseInt();
  bval = Serial.parseInt();
  tval = Serial.parseInt();
  vval = Serial.parseInt()+90;

  if(currentvolume < vval)
    {
    int diff = vval - currentvolume;
    pot.increase(diff);
    }
   else if(currentvolume > vval)
    {
    int diff = currentvolume - vval;
    pot.decrease(diff);
    } 
  currentvolume = vval;

  analogWrite(RED, rval);
  analogWrite(GREEN, gval);
  analogWrite(BLUE, bval);

  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(rval);
  lcd.setCursor(5,0);
  lcd.print(gval);
  lcd.setCursor(10,0);
  lcd.print(bval);
  lcd.setCursor(0,1);
  lcd.print(tval);
  lcd.setCursor(5,1);
  lcd.print(vval);
  lcd.setCursor(10,1);
  lcd.print(currentvolume);

  tone(2, map(tval,0,100,100,4000));
}
}

CONCLUSIONS

It was difficult to wire and program the DigiPot to control the volume of the speaker because it was altering the frequencies of the "tuned" pin and hence the sound was broken. After many hours of trouble rewiring and rewriting it finally works as expected.

Tuesday, August 26, 2014

Wireless switches control (with LabView)


This is another idea I had at work: in the entertainment industry we often install distribution board and we have to walk a long way to switch something on and off. Sometimes concerts and festivals cover a large area and our distribution board can be anywhere. It would be useful to operate them wireless. It would be even better to get some data from them, for example how much current the loads are drawing on each phase, but I'll get there when I'm more expert. In this experiment I just want to control 8 switches with my Arduino, using a LabView interface and XBee radio transmitters. In the distribution board there will be relays to open and close 240V circuits using a 5V signal. In this example I'm switching on and off simple LEDs. When I wire up the distro, I just have to replace the LEDs with relays.
In this case I'm using an Arduino Mega ADK, to make sure I have enough pins to control the switches and an LCD screen.
I've chosen to control 8 switches because the serial communication between LabView and the Arduino uses 256 characters (1 byte), exactly the number of combination we can create with 8 switches (2^8). This way, we only have to send one character (= 1 byte) and we don't need to synchronize the devices or use delays. If we want to control more switches, or we want to send an analog value over 255, we would need to send a string. We will see this in the next experiment.
The wiring is as follow:

LABVIEW INTERFACE


For the LabView interface I've used the code from the example "Advanced Serial Write and Read" downloadable from the National Instrument website. I added 8 switches. They output a boolean value (0 or 1) which is multiplied by the power of 2 correspondent to that switch number:
Switch 1 output multiply by 2^0.
Switch 2 output multiply by 2^1.
Switch 3 output multiply by 2^2.
Switch 4 output multiply by 2^3.
Switch 5 output multiply by 2^4.
Switch 6 output multiply by 2^5.
Switch 7 output multiply by 2^6.
Switch 8 output multiply by 2^7.
The values are then added to form the byte we have to send to the arduino.
This number is between 0 and 255, and each number correspond to a switches configuration. for example: 84 means (1-off, 2-off, 3-on, 4-off, 5-on, 6-off, 7-on, 8-off). This byte is then sent to the serial port through the function VISA.



ARDUINO SKETCH

Now we program the arduino to read the value from the serial port and execute the commands:

#include <LiquidCrystal.h>
LiquidCrystal lcd(26, 27, 28, 29, 30, 31);
int newvalue;
int oldvalue = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
}
void loop()
{
 if(Serial.available() > 0) {
   newvalue = Serial.read();
   
   if (newvalue != oldvalue){
   lcd.clear();
   lcd.setCursor(0, 0);
   lcd.print(newvalue);
   oldvalue = newvalue;
   }
    digitalWrite(2, HIGH && (oldvalue & B10000000));
    digitalWrite(3, HIGH && (oldvalue & B01000000));
    digitalWrite(4, HIGH && (oldvalue & B00100000));
    digitalWrite(5, HIGH && (oldvalue & B00010000));
    digitalWrite(6, HIGH && (oldvalue & B00001000));
    digitalWrite(7, HIGH && (oldvalue & B00000100));
    digitalWrite(8, HIGH && (oldvalue & B00000010));
    digitalWrite(9, HIGH && (oldvalue & B00000001));
   }
 delay(5);
}

As usual, I attached an LCD screen to display the value of the byte received by the Arduino through the serial port. It has to be the same displayed on the LabView interface.

The XBees simply replace the USB cable. I just plug them in as I would plug in a USB cable, nothing changes at the end devices. I just have to remember the switch on the Arduino XBee Shield: it has to be on "USB" when I program the controller, and on "micro" when I use the XBee.


CONCLUSIONS



The device works as expected, but it has some limitations: the communication of one byte can only control 8 switches. In the next experiments I will try to send and read strings. Also, the number of switches shouldn't be limited to the number of pins, in the future I will use shift registers to control several switches using one pin.

Monday, August 11, 2014

Remote communication between Arduino and smartphone

I developed this little device to check an analog sensor installed in a remote area using my phone. The idea is to check the level of fuel in generators we install in remote areas. So far, we had to drive there to check and refuel them. Now, we can check the level of fuel in each generator anytime and we can organize a refuelling trip more efficiently, only when necessary. The communication between the Arduino and the phone are simple text SMS.

COMPONENTS AND WIRING

To interface the arduino to the GSM network you need a GSM shield and a SIM card. I recommend the genuine Arduino GSM/GPRS shield, which has more functions, but here I'm using a SIM900 GSM/GPRS shield, which is enough for this project, and much cheaper. In Australia I bought a 20$ Vodafone simcard because it lasts one year without recharging, but I pay more than 28c per SMS (national and international). I'm sure you can get a better deal if you have time to look around.

The sensor: my employer gave me a fuel sensor to play with. It's a floating arm that moves the contact on a resistive rail. I measured the resistance across this resistor: 11 ohms when the arm is at the top (tank full), 185 ohms when the arm is completely down (tank empty). It's very important to know this value. The output value I want to see is a percentage from 0% (tank empty) to 100% (tank full).


If we connect this variable resistance in series with a fixed resistor we create a voltage divider: when we apply 5 volts we'll see a voltage drop across each resistor, and their sum will be 5 volts. The value of the fixed resistor should be about the same range of the variable. In this case I have a 68 ohms resistor. The voltage drop across resistors in series is proportional to their resistance. I wired up the circuit to measure the voltage drop across the fixed resistor with the analog input A5.


As usual, I connected a LCD to display the value in real time on the device.
The power comes from a 12V DC power supply in parallel with a 9.6V battery pack (8 x rechargable AA). When the generator is off, the batteries power the Arduino. When the generator is on, the power supply powers the Arduino and charges the batteries. To do that the power supply must have a higher voltage than the battery. The input voltage range (recommended) for the Arduino Uno is 7V to 12V.
It took me many hours to understand which pins are not used by the GSM shield. After many unsuccessful tries I was able to use pin 13,12,11,6,5,4 to run the LCD, without interfering with the operations of the shield.


SKETCH

We know the value read in the analog input is 0 to 1023, where 1023 correspond to 5 Volts. We have to apply Kirchoff Law to calculate the minimum and maximum value across the resistance, and then map this value to give an output value between 0 and 100%.

1023 * 68 / (185+68) = 275
1023 * 68 / (11+68) = 880

There is always a little error so, after few tries, I changed those values to 280 and 850 to give exactly 0 to 100% (it was close enough anyway).

I don't want to store the SMS on the SIM card, so I delete everything at the start of the program. This makes sure there is enough space to receive a command. Without this it stopped working suddenly and I couldn't understand why: the SIM was full.

A friend created an Android app to send a message to the device just pressing "test". The app sends a SMS starting with "a". The Arduino receive the message and it knows that "a" means "how much fuel is left?". It replies to the sender with the reading from the sensor.

Also, I want it to send an alarm SMS to a set "emergency phone" when the level of fuel passes the 50%, 25% and 10%.

#include <LiquidCrystal.h>
#include "SIM900.h"
#include <SoftwareSerial.h>
#include "sms.h"
SMSGSM sms;

LiquidCrystal lcd(13, 12, 11, 6, 5, 4);

int numdata;
boolean started=false;
char smsbuffer[160];
char n[20];
char sms_position;
char phone_number[20];
char sms_text[100];
int i;
char alarm_phone[20] = "+61439021813";

String dataString;
boolean alarm50 = false;
boolean alarm25 = false;
boolean alarm10 = false;


void setup()
{
  lcd.begin(16, 2);
  lcd.print("Testing...");
//  Serial.begin(9600);
//  Serial.println("GSM Shield testing.");
  if (gsm.begin(4800))
    {
//    Serial.println("\nstatus=READY");
    started=true;
    }
//    else Serial.println("\nstatus=IDLE");
  for(i=1;i<=20;i++)
    {
    sms.DeleteSMS(i);
    }
}

void loop()
{
  int val=(map(analogRead(A5), 280, 850, 0, 100));
  constrain (val, 0, 100);
  lcd.clear();
  lcd.print("Fuel:");
  lcd.setCursor(6,0);
  lcd.print(val);
  lcd.setCursor(9,0);
  lcd.print("%");
  delay(500);
 
  if(started)
    {
    sms_position=sms.IsSMSPresent(SMS_UNREAD);
    if (sms_position)
      {
//     Serial.print("SMS postion:");
//     Serial.println(sms_position,DEC);
      sms.GetSMS(sms_position, phone_number, sms_text, 100);
//      Serial.println(phone_number);
//      Serial.println(sms_text);
      sms.DeleteSMS(1);
      if(sms_text[0] == 'a')
        {
        dataString = "";
        dataString += "Fuel: ";
        dataString += (val);
        dataString += "%";
//        Serial.println(dataString);
        char charBuf[50];
        dataString.toCharArray(charBuf, 50);
        if (sms.SendSMS(phone_number, charBuf));
//        Serial.println("\nSMS sent OK");  
        }
      }
      else
      {
        if(val < 50 && !alarm50)
          {
          if (sms.SendSMS(alarm_phone, "Fuel < 50%"));
//          Serial.println("\nAlarm50 sent OK");
          alarm50 = true;
          }
          if(val < 25 && !alarm25)
          {
          if (sms.SendSMS(alarm_phone, "Fuel < 50%"));
//          Serial.println("\nAlarm25 sent OK");
          alarm25 = true;
          }
          if(val < 10 && !alarm10)
          {
          if (sms.SendSMS(alarm_phone, "Fuel < 50%"));
//          Serial.println("\nAlarm10 sent OK");
          alarm10 = true;
          }
//        Serial.println("NO NEW SMS,WAITING");
      }
  }
}

VIDEOS



Sunday, August 10, 2014

Binary to Gray, Gray to binary conversion


During my PLC course I had to convert binary numbers to Gray code and viceversa. I made this spreadsheet to help me with that.





Matrix solver (Cramer's rule)

This spreadsheet solve three equations with three variables using the matrix method (Cramer's rule).



Thursday, August 7, 2014

Brewduino

PURPOSE

I just finished testing my new experiment: a device that keeps the temperature of a fermenter between two set values and display and record the data over time. It takes about 6-7 days to ferment a home brew beer, and the temperature must be kept between 18 and 24 degrees (it can change slightly depending on the beer). If it's too cold the fermentation stops, if it's too warm the beer goes bad. I bought a 30W heating belt to wrap the fermenter, but I wanted it to go on and off automatically when needed, so I set up my Arduino Uno, a temperature sensor (DHT11) and a relay to control the AC current using a DC signal of 5 Volts. Additionally I attached an LCD to see the temperature read by the sensor and compare it with the analog thermometer, just to double check. I also like to analyse data so I attached an SD card module to record the temperature and state of the heating belt (on and off) over time.

SCHEMATICS



As you can see from the schematics, I'm using pin 5 to send the signal to the relay that controls the AC power to the heating belt. I decided to switch the active wire (brown): switching the neutral (blue) would work exactly the same but it wouldn't be safe in case of a fault. You can set the relay "normally open" (it will activate the circuit when the signal is present), or "normally closed" (it will stop the circuit when the signal is present) using different pins.
The SD card module uses 4 pins that are set in the relative library, so I didn't change them: they are 13,12,11,10 plus power and ground. These modules are supposed to work with both 3,3V and 5V but I can't get it to work with 5V so I had to use 3,3V. 
The sensor DHT11 has its own library and it only uses one pin (in this case pin 3) plus power and ground.
The connection of the LCD is always the same, with the potentiometer to control the brightness.

SKETCH

#include <LiquidCrystal.h>
#include <DHT11.h>
#include <SD.h>

LiquidCrystal lcd(9, 8, 7, 6, 4, 2);

int pin=3;
DHT11 dht11(pin); 

const int chipSelect = 10;
int t,h;

long previousMillis = 0;
long interval = 30000;

void setup(){
  Serial.begin(9600);
  pinMode(10, OUTPUT);
  pinMode(5, OUTPUT);
  lcd.begin(16, 2);
  if (!SD.begin(chipSelect)) {
    return;
  }
}

void loop(){
  int err;
  float temp, humi;
  if((err=dht11.read(humi, temp))==0)
  {
    t = (int) temp;
    h = (int) humi;
    
  lcd.print(t);

  if(t < 19){digitalWrite(5,HIGH);}
  if(t > 21){digitalWrite(5,LOW);}
    
  int state = digitalRead(5);
  lcd.setCursor(8, 0);
  lcd.print(state);

//  Serial.println(dataString);

  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > interval) {
    
    String dataString = "";
    dataString += "temperature:";
    dataString += String(t);
    dataString += ",";
    dataString += "humidity:";
    dataString += String(h);
    dataString += ",";
    dataString += String(state);
        
    File dataFile = SD.open("datalog.txt", FILE_WRITE);
    if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    }
    previousMillis = currentMillis;   
   }
  }
    delay(1000);
    lcd.clear();
}


To write the sketch I had to include the 3 libraries to control the LCD, DHT11 and SD module. I had to use pin 9,8,7,6,4,2 to control the LCD because I'm using 13,12,11,10 to control the SD module (and I can't change that unless I change the library). The "chipSelect" is pin 10 in the Arduino Uno (it's different in the Mega). Pin 3 is used by the sensor and pin 5 is the pin that controls the relay.
The sketch itself is pretty simple, I took parts from the datalogger sketch. I had to introduce a different kind of delay: I want the program to run every second, but to record data on the SD only every 30 seconds. To do that I can't use the function delay(30000), because it would stop the whole program for 30 seconds. I'm using the function millis() that counts the milliseconds passed since the start of the program. This value is compared to the set interval and when it's larger than that, it execute the part of the program that writes the data into "datalog.txt" on the SD card.
The function digitalRead() can also read an output pin. For example here I'm reading the state of pin 5, even though I'm using it as an output.

TEST

Because I don't want to waste beer, I filled up the fermenter with water for the purpose of this test. 


When you deal with higher voltages it's a good idea to enclose your devices in a box. 


After about 4 days I stopped the device and analized the data recorded on the SD card: I had 10545 values that correspond at about 88 hours of recording. As you can see from the chart, the temperature was kept between 19 and 21 degrees (the analog thermometer was reading the same). The last number in the log is the state of the heater (0=off, 1=on). The same value is displayed on the LCD, next to the temperature.

I imported this data into Excel and plotted a chart of temperature over time: as you can see the first day I had it set to keep the temperature between 18 and 24 degrees. The blue line indicates the temperature. The red line shows when the heater was on.


The heat belt was on for 11 hours to increase the temperature to 24 degrees, and the temperature decreased quickly after the heat belt went off. Then I changed the settings to make it work more efficiently: I just want to keep the temperatures over 18 degrees, so I set it to start the heat belt when the temp was under 19 and to stop when it was over 21. The second night it went on for a shorter time, enough to increase the temperature by 2 degrees (about 2 hours), the third night it didn't even go on because it wasn't cold enough and the fourth night it went on about 2.5 hours.

Analyzing data is useful to understand if the device is working efficiently or it can be improved. For example, I can observe that it takes about 1.5 hours to increase 23 liters by one degree, using about 30W of power.
I also plugged in a power meter at the heat belt to check the consumption: it uses maximum 40W power and at the end of the experiment the total energy consumption was about 680Wh.

Friday, May 23, 2014

Vectors operation in Excel


I made this spreadsheet to help me calculate the return current in unbalanced three phase loads. In this case the data to enter is the power factor and the magnitude of the current in each phase. The table will show the return current in complex number, polar and rectangular form. The chart will show the vector representing the current in the neutral conductor (in black).


The next spreadsheet calculates and plots the voltages across a resistor and an inductor (it can be easily changed to capacitor) in a series circuit. 


Example of Report

During my first semester of the Renewable Energy course I had to do some practical wiring and assembling of small solar power systems. The first task was to install a conduit according to a drawing. Even though this is a simple task, we always had to write a report about the practical work. This report is simple but complete and it has been used by other students as an example for more complex activities. I also drew the conduit with Google Sketchup to learn it. It's free and really easy.



Donwload the report
Download the drawing for Sketchup (.skp)

Wednesday, April 9, 2014

Plot sine waves with Excel


During my study I had to draw and calculate sine waves pretty often. I used Excel to plot them and calculate their sums or product.

This first file calculates and plots 3 sine waves in the same chart from their function (amplitude, frequency, shift and offset):


Download the file


The second file calculates and plots 2 sine waves from their function and their product, very useful to see the usage of power when voltage and current are not in phase:


Download the file


The third file calculates and plots 2 sine waves from their function and their sum. It also plots the phasor diagram at 0 degrees:


Download the file

Solar Microgrid


Today I’m sharing with you a project I’m particularly proud of. As final stage of my Renewable Energy course I was asked to complete a project of a stand-alone, hybrid system. Stand-alone means that the plant is not connected to the grid, like in a remote area. Hybrid means that more than one source of energy is used. In this case I designed a 27kW solar system with a backup diesel generator.
A microgrid is an independent grid where more than one unit can produce and use the power of the grid.
The purpose of the system is to power the irrigation system of a cherry farm, the owner’s house, a shed, and the farmstay for workers. The farm really exists and I worked in it, in Griffith NSW. It’s grid connected but I designed this system pretending that it wasn’t.
This is the final diagram of the complete system:

  

LOAD ASSESSMENT


The first step of a power system design is a load assessment. This stage allows us to understand the needs and the size of the system, but also to improve the energy consumption. In this case I was able to reduce it up to 30% in summer, improving the efficiency of the air conditioning.

  

Decreasing the energy consumption decrease the size of the system and of the components.
The next chart shows the load assessment of the 4 units (pump, house, shed and farmstay) combined, in different seasons.



DESIGN

To design this system I followed the Australian standards and the Clean Energy Council guidelines but I exceeded their requirements. I created a complex spreadsheet to help me in future design of this size.
The microgrid is a 3 phase system, the loads are spread across the phases equally, and only the irrigation pump uses the 3 phase power.
The following charts compare the power used in each phase at different time.



The system is designed to be expanded easily in the future.
In good weather conditions the sun (daytime) and the batteries (nightime) are enough to power all the loads. The generator starts automatically to power the loads and recharge the batteries in rainy days.
To calculate a perfect system I analysed the solar data (from NASA) and the load across the year and I considered the worst scenario. In this spreadsheet you can see the comparison between the load and the energy from the sun:


I also compared the performance of my arrays at different angles. I calculated that changing the tilt of the array just twice a year the annual output of the system increase considerably. To do that, we need an adjustable tilt array. The following chart compares the energy output of the system with a different tilt:
  

I made the following spreadsheet to help me in matching the inverter with the array, using the calculation suggested by the Australian standards and CEC. It also calculates the size of cables and circuit breakers. I need 6 inverters to collect the power from the 3 arrays and put it on the 3 phase grid.




ARRAY SIZE

To calculate the distances between the arrays (needed to calculate the length of cables and the voltage drop), avoiding shading between 10am and 2 pm, I made a spreadsheet that can be used in any area in Australia. You just insert the size and number of panels in the array, the tilt of the array, and the latitude of the location. The result will be the minimum distance between arrays to avoid shading when the system is more productive.



I copied the formula from the Clean Energy Council tech info released in March 2010. For some reason it’s not on their website anymore so you can download it here.



CUSTOMER MANUAL

As a final task I was required to write a customer manual, according to the Australian standards. It’s written in simple words to explain the basics of how the system works. It has to include important instructions and procedures.