Friday 27 May 2011

First project with the Jeenode and GLCD

 Having had my Jeenodes for a while now and eventually got some code to actually work, reading DS18B20s and displaying the results on a 16x2 line display, I fancied getting to grips with the GLCD, also from Jeelabs.
This is just a project to help me learn about the hardware and software, it may be useful in to someone out there.  I've tried to put plenty of comments in the code, mainly so I remember what I did when I look at it in two weeks time.

My target project is to create a portable (small) display that I can control the central heating from, i.e. room temp., heating on/off and hot water temp. control.  This project is the prototype phase.

At first it was a bit of a slog trying to understand the glcd library and how to send float variables to the screen (C++ is a new language for me), after that came the RTC coding to get the time on the screen, especially with leading zeros.

What I eventually came up with was a display showing the time, with leading zeros (thanks to 'sprintf'), two temperature inputs and a trend line showing just over two hours history for the current temperature.

The temperatures are derived from two DS18B20s connected to port2, adding extra sensors should be easy enough.  Each sensor has a Max. and a Min. point displayed.

The trend line is generated by sampling the temp. every minute, based on the now.minute() value from the RTC and then plotted between rows 40 to 60 using the glcd.setpixel command and the map function to map from 10 to 30 degrees C.  This time could be altered to be shorter or longer, as desired.

The hardware is basically a Jeenode V6, GLCD PCB and display, RTC plug (Port 3) and a DS18B20 soldered to a small prototyping board plugged into port 2.
DS18B20 on the Left and the RTC plug on the Right
 
On the DS81B20 PCB there is also a three pin right angle connector for the exernal DS18B20 probe, bought from Ebay.

The sofware is based on the Jeelabs demo sketches from Jeelabs rtcplug and the GLCD demo sketches.

The temperatures are also sent out over the serial link to the PC, formatted as they are seen on the GLCD. 

There are still some issues and some improvements to be made:-
  • The DS18B20 disconnected detection doesn't seem to work.
  • If the DS18B20 is disconnected and then, when reconnected, the Max temp. reads 85 Deg.
 Future improvements
  • To set the time I used another sketch but I plan to add the ability to set the time using my VB software from the PC.
  • Automatically alter the trend line scale based on the readings.
  • Round up the temp. for the pixel to the nearest degree.
  • Make the trend line update in seconds and put it in a variable. 

Next steps
  • Learn how to send/receive remote data from other Jeenode/Uno
  • Find out if I can use different size fonts on the GLCD (not the really big ones)
Sketch below: -
/* Based on Demo display for the Graphics Board and the rtcplug.pde from Jeelabs
 2010-11-14 <jcw@equi4.com> http://opensource.org/licenses/mit-license.php
 
 Added DS18B20 sensors and RTC plug
 Displays time, internal and external temp with min and max readings there is also a trend
 line drawn at the bottom of the LCD.  It samples the current temp. every minute, using RTC,
 and draws a pixel at a point between row 40 to 60, using the map command for temp's between
 10 and 30 degrees.  It takes 126 min's to draw the line then it clears the line and
 starts again.
*/
#include <GLCD_ST7565.h>
#include <Ports.h>
#include <RF12.h> // needed to avoid a linker error :(
#include <avr/pgmspace.h>
#include <OneWire.h>
#include "Wire.h"
#include <RTClib.h>
#include <DallasTemperature.h> //Version 3.6
#define ONE_WIRE_BUS 5  // DS18S20 Temperature chip i/o on pin 5 - Port 2

GLCD_ST7565 glcd;

EMPTY_INTERRUPT(WDT_vect);

OneWire oneWire(ONE_WIRE_BUS);// Setup a oneWire instance to communicate with any OneWire devices
DallasTemperature sensors(&oneWire);// Pass our oneWire reference to Dallas Temperature. 
// Global variables
char outBuf [25];
int MaxTempIn=0; //hold max temp value
int MinTempIn=500; //hold min temp value, pre load with 500 because the first test is against the temp val * 10  
int MaxTempOut=0; //hold max temp value
int MinTempOut=500; //hold min temp value, pre load with 500 because the first test is against the temp val * 10 
int LastMin; //Hold last min value
int x=1; //counter for trend line
int Ypixel; // Y value for trend line
// Insert the ID of your temp sensor here, for the sketch, visit here
// http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html
DeviceAddress insideThermometer = { 0x28, 0x2F, 0x8A, 0xEE, 0x02, 0x00, 0x00, 0xE9 }; // none probe
DeviceAddress outsideThermometer = { 0x28, 0x60, 0x3A, 0x10, 0x03, 0x00, 0x00, 0x38 };
DeviceAddress WaterThermometer = { 0x28, 0xB3, 0x58, 0x18, 0x03, 0x00, 0x00, 0x2B };
class Sleepy;

// RTC based on the DS1307 chip connected via the Ports library
class RTC_Plug : public DeviceI2C {
    // shorthand
    static uint8_t bcd2bin (uint8_t val) { return RTC_DS1307::bcd2bin(val); }
    static uint8_t bin2bcd (uint8_t val) { return RTC_DS1307::bin2bcd(val); }
public:
    RTC_Plug (const PortI2C& port) : DeviceI2C (port, 0x68) {}

    void begin() {}
    
    void adjust(const DateTime& dt) {
        send();
        write(0);
        write(bin2bcd(dt.second()));
        write(bin2bcd(dt.minute()));
        write(bin2bcd(dt.hour()));
        write(bin2bcd(0));
        write(bin2bcd(dt.day()));
        write(bin2bcd(dt.month()));
        write(bin2bcd(dt.year() - 2000));
        write(0);
        stop();
    }

    DateTime now() {
       send();
       write(0); 
        stop();

        receive();
        uint8_t ss = bcd2bin(read(0));
        uint8_t mm = bcd2bin(read(0));
        uint8_t hh = bcd2bin(read(0));
        read(0);
        uint8_t d = bcd2bin(read(0));
        uint8_t m = bcd2bin(read(0));
        uint16_t y = bcd2bin(read(1)) + 2000;
    
        return DateTime (y, m, d, hh, mm, ss);
    }
};

PortI2C i2cBus (3); //RTC on port 3
RTC_Plug RTC (i2cBus);

void setup () {
DateTime now = RTC.now();
LastMin = now.minute(); //Store minute value for use in Draw Graph

// Set serial speed
  Serial.begin(57600);
  // Start RTC
 RTC.begin();
// Power down the Transceiver
    rf12_initialize(1, RF12_868MHZ);
    rf12_sleep(0);
// Start the temp sensors    
    sensors.begin();

// set the resolution to 12 bit
    sensors.setResolution(outsideThermometer, 12);
    sensors.setResolution(insideThermometer, 12);
 //sensors.setResolution(WaterThermometer, 12);
    Wire.begin();

 // Initialise the GLCD
    glcd.begin();
    glcd.backLight(255);
    glcd.drawString_P(0,  10, PSTR("       Now  Max  Min")); //Set the column titles
    //glcd.drawLine(0, 8, 120, 8, WHITE);
    glcd.drawRect(0, 8, 128, 56, WHITE);
    glcd.refresh(); // Update the display
}

void loop () {
 DateTime now = RTC.now();
  sensors.requestTemperatures();// Trigger all the temp sensors to carry out a temp. conversion 
  Sleepy::loseSomeTime(2000); // Do nothing for n seconds, slow update OK
 
  printTemperature(insideThermometer); // Read in the temp. data from the inside sensor
  printTemperature(outsideThermometer); // Read in the temp. data from the outside sensor
  UpdateTime();
  //Trigger a pixel to be drawn on the history every minute
  if(now.minute() > LastMin) {
    DrwGraph();
    LastMin = now.minute();
  }
  if(LastMin > now.minute()) {
  LastMin=1; //reset to 1 as rollover to next hour.
  }
  glcd.refresh();
 }
 
void UpdateTime(){ 
 DateTime now = RTC.now();
 sprintf(outBuf, "Time %02d:%02d",now.hour(), now.minute()); //Format the time without seconds
 glcd.drawString(3, 0, outBuf); //Print to Screen RAM
 Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.print(" - ");
    Serial.print(now.day(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.year(), DEC);
    Serial.print("\n");
  }

void printTemperature(DeviceAddress deviceAddress) {
int temp2; // Create variable to hold the int value of the float without the decimal 
float tempC = sensors.getTempC(deviceAddress); // read the specific sensor called from loop.

if (deviceAddress == insideThermometer){ //Display Internal Temp

if (tempC == -127) {
      glcd.drawString(10,  20, PSTR("Error"));
} else {
  temp2 =tempC *10 + 0.5; // make now temp decimal value into an integer. remove decimal point
  Ypixel = temp2/10; // Store Y pixel value temp for trend line
  if (MaxTempIn < temp2){ //Set MaxTempIn to temp2 if higher than old MaxtempIn
    MaxTempIn=temp2;
}
if (MinTempIn > temp2) { //Set MinTempIn to temp2 if Lower than old MinTempIn
 MinTempIn = temp2;
}
  // Print Inside Temps, Now, Max and Min.
  //Format the integer back into integer and decimal 
  sprintf(outBuf, "In    %d.%d %d.%d %d.%d",temp2/10, temp2%10,MaxTempIn/10, MaxTempIn%10,MinTempIn/10, MinTempIn%10); 
  glcd.drawString(3, 20, outBuf); //Print to Screen RAM
  Serial.print("      Now  Max  Min");
  Serial.print("\n");
  Serial.print(outBuf); //send data to host 
  Serial.print("\n");
}
}v 
if (deviceAddress == outsideThermometer){ //Display Outside Temp
if (tempC == -127) {
      glcd.drawString(10,  30, PSTR("Error"));
} else {
  temp2 =tempC *10 + 0.5; // make now temp decimal value into an integer. remove decimal point
  if (MaxTempOut < temp2){ //Set Max temp2 if higher than old Maxtemp
    MaxTempOut=temp2;
}
if (MinTempOut > temp2) { //Set Min temp2 if Lower than old Mintemp
 MinTempOut = temp2;
}
// Print Outside Temps, Now, Max and Min.
//Format the integer back into integer and decimal 
  sprintf(outBuf, "Out   %d.%d %d.%d %d.%d",temp2/10, temp2%10,MaxTempOut/10, MaxTempOut%10,MinTempOut/10, MinTempOut%10);
  glcd.drawString(3, 30, outBuf); //Print to Screen RAM
  Serial.print(outBuf); //send data to host 
  Serial.print("\n");
}
}
}
void DrwGraph(){ //Plot next pixel of temp history
if (x < 126){ //Check if the end of the visible screen is reached
x++; //Increment x for next pixel
// draw pixel, Y value mapped from temp value to Y pixel range, reversed.
glcd.setPixel(x,map(Ypixel,10,30,60,40),WHITE); 
}
else{
glcd.fillRect(1,40,126,20, BLACK); //Draw rectangle in Black to erase previous line
x=1; // Start at left hand of visible screen again.
}
}

Thursday 19 May 2011

Really Really small Oscilloscope

I came across this post on the Jeelabs website and thought it was worth posting.
Dual Channel Oscilloscope and waveform generator
This thing is about the size of a 9V PP3 battery, based on an ATXMEGA32A4 processor with a 0.96" white OLED display it includes the functionality of a dual channel oscilloscope, multimeter, protocol sniffer and waveform generator.

It can be found here and there are some videos of it in operation here.

Multimeter mode
The firmware can be updated but it needs a special USB/programming cable and it will, in the future, be connectable to the PC and use PC based interface.

The waveform generator operates independently from the scope function so you can apply the signal to a filter circuit and watch the results on the scope.

It's also possible to write your own software and use it for other projects, there is one picture on the site showing it displaying temperature from a DS18B20.  I think this requires a special programmer though.

All for a price of $49, a bargain!

I don't know about availability in the UK but If anyone sees it for sale in the UK please make a comment.

Tuesday 10 May 2011

Next consumer computing phase ?

Every now and then something comes along that changes people's attitudes towards technology, for me there was VHS/Betamax video recorder, the Commodore VIC20, the BBC Micro, the CD player, to name a few.

For me, the main impacts have always been with the introduction of new computing technologies, like the first Toshiba dual floppy DOS based laptop I had access to at work, closely followed by my own 286 Turbo PC I built at home.

The last key step in computers, for me, was the Netbook, inspired by the goal to supply cheap computing to the third world it soon became a whole new platform that was so much more portable.

Of course there is tablet computing but as yet I've not found the need to spend the money to go there!

Now there is a branch of computing technology to embrace and it looks like it will be very affordable, the Raspberry Pi.

Being developed by the Raspberry Pi Foundation, a UK registered charity, they hope it will become an ultracheap computer platform to be used to teach childeren about computing.  It may even be cheap enough for them to be given to school children, around £15.

The ultra small device features an HDMI port at one end and a USB port on the other.

There is a Youtube video here.

Monday 9 May 2011

Free Web based Autorouting software

In my internet travels I came across a really useful site for autorouting PCBs, the application is Java based and runs from the website.
It's compatible with most main PCB design SW like the free version of CADsoft-Eagle and even though it's still in the development phase, its on-line version is free to use.
So if you've got a nice Arduino clone design and you want to optimise the PCB by reducing the amount of vias you have then give it a try, if you haven't got a PCB ready then you can still give it a try with the demo files supplied.
The site can be found here http://www.freerouting.net/

Sunday 8 May 2011

Jeenodes are here

At last my Jeenodes arrived and I started to programme them with some of the code I was using on the Arduino UNO to display temperatures from a DS18B20 on the LCD.

I was now using the I2C LCD interface from Jeelabs (LCD Plug) so I used the Demo LCD sketch from Jeelabs and modified it using the Dallas temperature library to read a DS18B20 conected to port 4.

Jeenode V6 with DS18B20 and I2C LCD

I have the Graphic board on order so I can use a large display and, using the code from Jeelabs, create a remote temp. sensing and control unit for my central heating control project.

The built in 868MHz Transciever will allow comm'.s back to the control unit in the airing cupboard.

Hopefully with the efforts made by Jeelabs to extend battery life I hope to get months of usage from a couple of AA batteries.

Three button WiFi Remote

Using the power control circuit from the Wirelesse door/Window sensor I have designed a simple 3 button WiFi remote with the intention of co...

Popular Posts