Sunday, November 25, 2012

Frustration

I am frustrated.  About a lot of things - but mostly about my inability to get the nrf24l01 radio and any Ethernet adapter to coexist on an Arduino. I have three Ethernet shields - a very old one from Adafruit, one of the latest Arduino versions, and a ENC28J60 Chinese module I got off eBay.

I use the rf24 library and it is wonderful for talking to the radio and it makes things quite simple, and rock solid.  There are various Ethernet libraries for the ENC28J60 - and it seems that I have tried them all.

When I use either Ethernet or the RF24 separately  it works. But trying to combine it into the same sketch either it won't start, or something collides in the software libraries and I strange behavior, but no connectivity.

They both use SPI and the I am lead to believe that using the CS (Chip select) to turn one chip off allows the other to take over and use the SPI *bus*. But since I am using libraries i do not quite know if they are behaving normally and releasing their chip select each time.

My goal, which seems simple and straight forward enough, is to take readings from various sensors inside and outside and send them off to ThinkSpeak, COSM, WeatherUnderground.  I have a small C# app I run on the desktop, but that means I have to leave the computer on 24/7 and burning up all that power. Plus the C# app interferes with some of the other things I do on the desktop and consumes a lot of resources besides.  I seem to be killing the app often to read the mail or whatever and forgetting to turn it back on.

So all I need is a standalone Arduino sketch to send the data in.  So far no luck.  I have goggled to try and find someone else that has managed this task, but no one seems to have done it, or is not publishing how they did. Clos4est I got was a post Fixing an enc28J60 based Arduino Mega ethertnet shield 

I will  be trying this hack out - but there is precious little detail.   Wish me luck.


Tuesday, November 13, 2012

Sunday, October 28, 2012

The oncoming storm got me off my duff and put an old tipping bucket rain gauge left over from a failed weather station.  I haven't a clue how much each tip counts toward inches, so I just going to count them for the time being.

If history is any indication - the wind will blow the rain gauge over (away) it usually did in the past.  I looked around for a cinder block to anchor it down with, but am fresh out. (BTW - try and find a flashlight anywhere around :-)

If the wind gets that bad - will probably knock out the power and this long chain of technology (Arduino -> nrf24l01+ -> arduino -> serial -> Desktop -> C# -> COSM ) will break and that will be that. Everything is battery backed up except for the desktop, the weak link in the chain.

The data can be seen @ https://cosm.com/feeds/74950https://cosm.com/feeds/82947 I know it is really, really messy, but the good stuff is there.  Look for outside temperature (OT) OutsideTips (count of the rain bucket tips), and the Barometric Pressure. The Barometric Pressure should see a really low value if it gets bad.

Now all I have to do is knuckle down and build the anemometer, the last part of the weather station.  I have this insane desire to use a child's pinwheel to measure the wind - all i really need to know is 1)is is calm, and 2)blowing light, medium, hard.  If i need facts - weather channel, weather underground, or AccuWeather will give me all that.

That and get it all working with a Ethernet card of some kind. (Raspberry Pi?)

Tuesday, September 25, 2012

COSM and smooting

Been quite busy this weekend.  I worked on the C# application that sends the sensors to  COSM   https://cosm.com/feeds/74950.

I also soldered the parts onto a expansion shield and put it out on the front porch.  

The Arduino code was reworked to separate the local base station sensors from the external sensors.  I implemented that with RF24Network, so I could put a few more sensors/radios around the house.

I had to change the C# code to allow for different nodes and send each separable to COSM.  The base station is node 0, the external sensor(s) will be 1-6 or so.

After looking at everyone's jaggies in the lines on all the graphs - I went looking for a smoothing function on the net - you would be amazed haw hard it was to find one and then wrap my mind around once it did. I took  statistics and don't remember this exact algorithm.  But it boils down to:

avg = x * prev_avg + (1 - x) * sample; 

You maintain the prev_avg for each sensor that you want to smooth - and you monkey around with the value of x which is in the range of 0

It gives really strange values on  COSM like 30.166451344586.3 Gota love double precision numbers for the Barometric pressure - but the graph looks a lot better.

Now on to hooking up the rain gauge and the light sensor.
 

Saturday, September 15, 2012

C# Arduino ThingSpeak and COSM


I bit the bullet and put together a C# app to read the serial from my Arduino weather station and send it to COSM (Pachube) and Thing Speak.  The Ethernet shield library for the Arduino has memory problems and with all the other things going on in the Arduino sketch it locks up after a few minutes. That part of the project is on the back burner for a while

I had tried a few times before to get a serial monitor between the Arduino and the computer using various libraries and languages.  All to no avail.  However if you dig around on the net long enough you can get libraries and code that others have used and cobble it together to get the job done.

I found some Rs232 code here.   I found a ThingSpeak class here. I found some COSM code here. Cobbled it together, got it working and put it up on Google Code.

Believe it or not - Google code was the hardest part - Had to install TortoiseHg/Mecurial and figure that all out and then figure out how to get it into Google.  Let me just say if you want to do the same - it works backwards from what you think.  Build the Google Repository - then clone it to your local machine, copy your source there and push it back to Google.

You have to configure ThingSpeak manually, The settings are a simple check-box for each new graph, and you push the data as field1, field2e.t.c.  However a nice thing about COSM is that it picks up what you send to your channel. and auto creates a data-set to graph.  I plan to exploit that a little more when I get the Radios working again and have sensors all over inside and outside the house.

Please excuse the code - It is incredibly raw, and it will take some time to massage it into reusable classes.

I found some interesting .NET classes for Gauges here and here but haven't taken the time to plug the code in yet.

Sunday, July 15, 2012

Working Prototypes

Inside Station plugged into the computer.

Outside on the front porch running on battery.. Under cover so the rain doesn't get to it too much.  Two days on the Li-ion battery and it still shows ~4 volts. Almost fully charged.

Since the radio is using SPI, I set the display up as I2C, I follow the two rules of micro controllers - Unused memory is wasted memory, and Unused pins are wasted pins.

The data is being sent to  https://thingspeak.com/channels/2624 - I am going to try and let it run for a few days and not monkey with the code too much.  I have code to measure the battery voltage - but I am going to resist it for the time being, and just let it run...




Friday, July 13, 2012

DIY Remote Temperature Logging Software



I bread boarded all the parts together using the default pin numbers mentioned in each part's documentation and started investing time in getting the software working together.

Once I get a schematic editor working - I'll get the schematic here. Sorry for any delay

The software and Libraries that it took to make it all work.

RF24 - This is used to drive the radios. The PingPair_Sleepy example sketch is the basis of the project.  Getting two Arduinos working on the same computer is a bit of a challenge.  It helps that with this sketch the two Arduino are running the same code.  Who is talking and who is listening is controlled by pin7.  If it is high - you are the talker and if pin7 is at ground - that Arduino is listening, a nice touch. The pin7 is tested and routes the program flow to the proper code to talk or listen. It helps that you actually run a jumper from pin7 to VCC+. It gets somewhat iffy if it is just left floating and assumed to be high.

I got stuck at first by changing the code to send an array of floats over the radio.  I got confused by declaring the array length and actually accessing its members.  I originally used ht[1] as the two value array.  I needed to have declared it as ht[2] and then reference it as ht[0], and ht[1].  Even though it worked in the sketch declared as ht[1] - when it came to sending the values to the radio using radio.send (&ht,sizeof(ht)) the size of returns the declared array size in bytes which is  4 for 1 member array of float and sent only one value of the array.  The compiler must have stuck a little extra space in memory that allowed a second value in a 1 character array.  Watch out for this.

DHT22 - Adafruit does such a nice job with their libraries and examples.  This was used to get the temperature and humidity from the DHT22 sensor to send back and forth.
Very straight forward - not any problems with library at all.

NueWire's Seriot - Currently I am using this application to send the data to ThingSpeak for display.  It was a bit of a challenge to get it set up and having it send all three values I wanted to graph.  It listens to the serial port and I rotate between the three different values sent 15 seconds apart.  Thing Speak will not allow updates closer than 15 seconds apart.


The Thing Speak Setup is


The operative part of the Seriot config file is


add key="tsSensor-1" value="APIKEY,field1,OutsideTempF"
add key="tsSensor-2" value="APIKEY,field2,OutsideHumidity"
add key="tsSensor-3" value="APIKEY,field3,OutsideTempC"

The data is sent from the sketch as:

###BOD
OutsideTempF,88.52
###EOD


How it all hooks together is:

  • Seriot matches up the first string in the csv line with its matching value in the config file (case counts)
  • Seriot then constructs a call to ThinkSpeak using the field# on the matching line in the file - evidently it only sends one value each call.  I had to put a 15sec wait in the sketch and then rotate through the 3 values to get them all posted using the same APIKEY.
Eventually I will have an Ethernet shield doing this, but the breadboard and the parts on the expansion shield doesn't give enough clearance to plug one in.  I was impatient to get something working so I went this route while I still had a change to move wires around.

Current Arduino Sketch
------------------------------------------------------


#include <SPI.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"
#include "DHT.h"

//DHT specific declarations
#define DHTPIN 2     // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)
DHT dht(DHTPIN, DHTTYPE);

//store the vales to transmit 0= humidity, 1=temp
float ht[2];

//pins used by the nRF24L01 radio chip module
RF24 radio(9,10);

// sets the role of this unit in hardware.  Connect to GND to be the 'pong' listener
// Connect to 5v to be the ping talker
const int role_pin = 7;

// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
typedef enum { role_ping_out = 1, role_pong_back } role_e;
const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"};

// The role of the current running sketch
role_e role;

// Sleep declarations
typedef enum { wdt_16ms = 0, wdt_32ms, wdt_64ms, wdt_128ms, wdt_250ms, wdt_500ms, wdt_1s, wdt_2s, wdt_4s, wdt_8s } wdt_prescalar_e;
void setup_watchdog(uint8_t prescalar);
void do_sleep(void);
const short sleep_cycles_per_transmission = 4;
volatile short sleep_cycles_remaining = sleep_cycles_per_transmission;
  int counter=0;
void setup(void)
{
   //used to rotate through the three data values sent to ThingSpeak
   counter=0;
  // set up the role pin
  pinMode(role_pin, INPUT);
  digitalWrite(role_pin,HIGH);
  delay(20); // Just to get a solid reading on the role pin
  // read the address pin, establish our role
  if ( digitalRead(role_pin) )
    role = role_ping_out;
  else
    role = role_pong_back;

  Serial.begin(9600);
  //initialize the DHT22 library
  dht.begin();
  printf_begin();
  printf("\n\rRF24/examples/pingpair_sleepy/\n\r");
  printf("ROLE: %s\n\r",role_friendly_name[role]);
  // Only the ping out role sleeps.  Wake up every 4s to send a ping
  if ( role == role_ping_out )
    setup_watchdog(wdt_1s);
  // Setup and configure rf radio
  radio.begin();
  // Open pipes to other nodes for communication
  if ( role == role_ping_out )
  {
    radio.openWritingPipe(pipes[0]);
    radio.openReadingPipe(1,pipes[1]);
  }
  else
  {
    radio.openWritingPipe(pipes[1]);
    radio.openReadingPipe(1,pipes[0]);
  }
  // Start listening
  radio.startListening();
  // Dump the configuration of the rf unit for debugging
  //radio.printDetails();
}

void loop(void)
{
  // Ping out role.  Repeatedly send the current time
  if (role == role_ping_out)
  {
    //get the data from the dht22
    printtemp();
    // First, stop listening so we can talk.
    radio.stopListening();
    // Take the time, and send it.  This will block until complete
    printf("Now sending ");
    Serial.print("sizeog(ht) ");
    Serial.println(sizeof(ht));
    radio.write( &ht, sizeof(ht) );
    // Now, continue listening
    radio.startListening();
    // Wait here until we get a response, or timeout (250ms)
    unsigned long started_waiting_at = millis();
    bool timeout = false;
    while ( ! radio.available() && ! timeout )
      if (millis() - started_waiting_at > 250 )
        timeout = true;
    // Describe the results
    if ( timeout )
    {
      printf("response timed out.\n\r");
    }else{
      // Grab the response, compare, and send to debugging spew
        // Spew it
      radio.read( &ht, sizeof(ht) );
      printf("Got response \r\n");
      Serial.println (ht[1]);
    }
    // Shut down the system
    // Experiment with some delay here to see if it has an effect
    delay(500);
    // Power down the radio.  Note that the radio will get powered back up
    // on the next write() call.
    radio.powerDown();
    // Sleep the MCU.  The watchdog timer will awaken in a short while, and
    // continue execution here.
    while( sleep_cycles_remaining )
      do_sleep();

 sleep_cycles_remaining = sleep_cycles_per_transmission;
  }
  // Pong back role.  Receive each packet, dump it out, and send it back
  if ( role == role_pong_back )
  {
    // if there is data ready
    if ( radio.available() )
    {
      // Dump the payloads until we've gotten everything
      bool done = false;
      while (!done)
      {
        // Fetch the payload, and see if this was the last one.
        done = radio.read( &ht, sizeof(ht) );
        // Spew it.
        //printf("Got payload %lu @ %lu...",got_time,millis());
        //printf("Got payload ...");
//if (isnan(ht[0]) || isnan(ht[1])) {
if (isnan(ht[0]))
        {
          Serial.println("Failed to read from DHT");
        } else {
//convert the temperature to F
float f=(ht[1] * 9.0 / 5.0) + 32.0;
          if (counter==0){
          Serial.println("###BOD");
          Serial.print("OutsideTempF,");
          Serial.println(f);
          Serial.println("###EOD");
          }
          else if(counter==1){
          Serial.println("###BOD");
          Serial.print("OutsideHumidity,");
          Serial.println(ht[0]);
          Serial.println("###EOD");
          }else if (counter==2){
          Serial.println("###BOD");
          Serial.print("OutsideTempC,");
          Serial.println(ht[1]);
          Serial.println("###EOD");
        }
          if(++counter>2) {
          counter=0;
        }
        }//endif isnan
      }//endif radio.available()

      // First, stop listening so we can talk
      radio.stopListening();
      // Send the final one back.
      radio.write( &ht, sizeof(ht) );
      //printf("Sent response.\n\r");
      // Now, resume listening so we catch the next packets.
          delay(15000);//need to put the delay in the ping out code block to sleep longer (later)
      radio.startListening();
    }
  }
}

//gets the data from the DHT22 sensor and sends it to the serial port (only on the sender)
void printtemp()
{
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  ht[0]=h;
  ht[1]=t;
  // check if returns are valid, if they are NaN (not a number) then something went wrong!
  if (isnan(t) || isnan(h)) {
    Serial.println("Failed to read from DHT");
  } else {
    Serial.print("Humidity: ");
    Serial.print(ht[0]);
    Serial.print(" %\t");
    Serial.print("Temperature: ");
    Serial.print(ht[1]);
    Serial.print(" *C\t");
    t = (t * 9.0 / 5.0) + 32.0;
    Serial.print("Temperature: ");
    Serial.print(t);
    Serial.println(" *F");
 
  }
}
// Sleep helpers
// 0=16ms, 1=32ms,2=64ms,3=125ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(uint8_t prescalar)
{
  prescalar = min(9,prescalar);
  uint8_t wdtcsr = prescalar & 7;
  if ( prescalar & 8 )
    wdtcsr |= _BV(WDP3);

  MCUSR &= ~_BV(WDRF);
  WDTCSR = _BV(WDCE) | _BV(WDE);
  WDTCSR = _BV(WDCE) | wdtcsr | _BV(WDIE);
}

ISR(WDT_vect)
{
  --sleep_cycles_remaining;
}

void do_sleep(void)
{
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
  sleep_enable();
  sleep_mode();                        // System sleeps here
  sleep_disable();                     // System continues execution here when watchdog timed out
}

// vim:ai:cin:sts=2 sw=2 ft=cpp


Saturday, July 7, 2012

DIY remote temperature Logger - Bits and Pieces

Ever since my weather station console fell off the computer table and broke the LCD, I have wanted to DIY a replacement.  Since we have the heat wave - I am inspired again.
Goal -

  • Outside arduino battery (solar?) radio sender
  • Inside Arduino console - linked to a site that graphs the data
Plan -

  • Document each sub system in separate Blog posts.


This post outlines the Hardware I accumulated for this project.

You will notice that I have a lot of different breakout board modules - For the first go round it is always better, for me, to have an already built module that has been debugged, than to start from scratch.  It might be cheaper to start with all the parts and build it out, but it certainly takes a lot more time. After it all works, I might, and that is a remote might, build a custom board.  But it is highly unlikely.


3.7V/670mAh Rechargeable Lithium-Ion
The battery was a close out - had internal protection circuitry and 650mah - more than enough to drive a sleepy Arduino for a long time,

Lithium rechargeable batterys are dangerious to charge - so I found this on eBay  A bit pricey but it suited me.  It's default charge current was a healthy one amp so I had to replarce the current set resistor to limit the current to ~35% of C for the battery (~4.7K for 350ma).   Little tiny surface mount resistors are out of the question for someone with my eyes. I used a 1/8w resistor on one and a trimmer pot on the other.

Item image


NRF24L01 radio  They are all over eBay for all prices - I got mine from Digole Digital Solution in Canada and they arrived in just a few days.  I have done business with them in the past and liked them.  The Library I found to work the best for this board on the Arduino is the Maniacbug RF24


Item image

Serial Display Adapter - I had a 16X2 display and never managed to include it into any project - simply because it took too many pins and too much code. Since I was on  Digole - got a couple.  A little disappointed that it did not include a command to turn the back light on and off - but that was a very minor point.

Diavolino
Diavilino - My favorite Arduino clone.  The Evil Mad Scientist basic kit costs around  around  $12 -  The biggest plus is that they take all the shields. I have a BUNCH of them.
 I never included the voltage regulator on any board - have always run them from batteries. Mostly 3 AA's. But for this project I thought I would need the Li-Ion - just because I wanted too.  They run @ 16mhz just fine on batteries.

DHT22  temperature-humidity sensor + extras


DHT22 temperature-humidity sensor From Adafruit  Something I had from a while back.



Proto Shield from Adafruit   Eventually when I get enough time, everything will be soldered onto one of these. I can and have created custom circuit boards in the past - but for one offs - nothing beats prototyping with  this shield - usually with a mini solderless breadboard on top. The after all the kinks are worked out - solder it down and call it done.


Monday, February 20, 2012

Valentines for the honey - Astonishment for me

I took one of my Jimmy Rodgers heart kits - gussied it up with some silk flower petals - hooked it to an older  Adafruit Boarduino and gave it to my honey for Valentines.  I used 3 dollar store AA's as power.   She put it up on the Mantel and there it sits - for a week now - happily blinking away.  I am astonished at how long the batteries are lasting - she is loving the gift I made her.  I guess we are both happy.