Arduino Wireless Logging, Post Two: The Design

This is the second part of the series for my Arduino wireless project I’ve been working on for a couple weeks now. You can start reading from the first post: https://aasullivan.com/?p=1146.

We have the idea, now we have to build it. I have three Arduinos set up at this point in this manner:

  • (1) Set up as wireless receiver/hub; this will read data, print to Serial and log to ethernet eventually
  • (2) Transmitters which simply read data every ~5 seconds to blindly send to receiver (node 0)

This layout will allow me to test from a couple devices to make sure the layout of the node IDs will work properly and be read properly as well. I ran into my first set of issues at this point: I can only read one Arduino at a time off Serial from the IDE, so went and imaged an older Dell D630 to handle the receiving end of things to troubleshoot the payload issues I ran into. 

So, massive issues begin once first code goes into place and I learn how difficult it is to troubleshoot wireless data transfers when I cannot tell if it’s a receiver or transmitter issue. After many frustrating hours, I finally get a build working that transmit static values from one node to one hub. Mind you, this doesn’t include the actual ethernet logging as this was a whole new issue (will explain in later post).

Code is below, should have enough comments to understand the general idea behind it. For now, this will take data from a DHT11 temp/humidity sensor along with voltage readings and push this to the main hub/receiver node, which will read and push this to the Serial read bus.

Hope this is helpful, in the next post I’ll go over the updates to the SPI set up when using both the RF24 modules and an ethernet shield at the same time. Cheers!

Code for original build, receiver:

#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>

// Number of Temperature sensors
#define NumNodes 3
// nRF24L01(+) radio attached 
RF24 radio(9,10);
// Network uses that radio
RF24Network network(radio);
// Channel of our node
const uint16_t channel = 90;
// Address of our node
const uint16_t this_node = 0;

// Structure of our payload
struct payload_t
{
 unsigned long counter;
 float tempC;
 float tempF;
 float Vcc; // 4 bytes
};

// Since nodes start at 1, I added 1 to arrays to make it easier
unsigned long NodeCounter[NumNodes+1];
float NodeTempC[NumNodes+1];
float NodeTempF[NumNodes+1];
float NodeVcc[NumNodes+1];

//Prototypes for utility functions
void getRadioData(); // get Radio data

void setup(){
 //Start Serial
 Serial.begin(57600);
 Serial.println("Temperature Data");
 
 SPI.begin();
 // Radio setup
 radio.begin();
 // network.begin(/*channel*/, /*node address*/);
 network.begin(channel, this_node);
 
}

void loop() {
 // Pump the network regularly
 network.update();
 // Is there anything ready for us?
 while ( network.available() ){
 // If so, grab it and print it out
 getRadioData();
 }
 delay(100); }

//////////////////////////////////////////////////////////////////////////////////
// getRadioData() // get Network data
//////////////////////////////////////////////////////////////////////////////////
void getRadioData(){
 RF24NetworkHeader header;
 payload_t payload;
 bool done = false;
 
 while (!done){
done = network.read(header,&payload,sizeof(payload));

NodeCounter[header.from_node] = payload.counter;
 NodeTempC[header.from_node] = payload.tempC;
 NodeTempF[header.from_node] = payload.tempF;
 NodeVcc[header.from_node] = payload.Vcc;
 
 Serial.print("Received packet #");
 Serial.print(NodeCounter[header.from_node]);
 
 Serial.print(" from node#: ");
 Serial.print(header.from_node);
 
 Serial.print(" TempC: ");
 Serial.print(NodeTempC[header.from_node], 1);
 Serial.print(" TempF: ");
 Serial.print(NodeTempF[header.from_node], 1);
 Serial.print(" Vcc: ");
 Serial.println(NodeVcc[header.from_node], 1);
 }
}

Code for transmitter:

//Updated Send Node to send from DHT data pulled from PIN2

#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
#include "DHT.h"

//Define DH information
#define DHTPIN 2
#define DHTTYPE DHT11 // DHT 11
//Set DHT options
DHT dht(DHTPIN, DHTTYPE);

float humid;
float temp;

int sleepDelay = 5000; // in milliseconds

// nRF24L01(+) radio attached (CE, CSN)
RF24 radio(9,10);
// Network uses that radio
RF24Network network(radio);
// Channel of our node
const uint16_t channel = 90;
// Address of our node
const uint16_t this_node = 1;
// Address of the other node
const uint16_t other_node = 0;

// How many packets have we sent already
unsigned long packets_sent;

// Structure of our payload, limited to 32 bytes
struct payload_t // 32 bytes max
{
unsigned long counter; // 4 bytes
float humid; // 4 bytes
float temp; // 4 bytes
float Vcc; // 4 bytes
};

// Analog pins
#define VccPin 0
// Digital pins
#define ActivePin 7

float Vcc; //Supplied Voltage

// Prototypes
void getVoltage(); // getVoltage
void getStats(); // get DHT stats
void sendPayload(); // check if time to send payload
void setup(void)
{
//Serial.begin(57600);
analogReference(INTERNAL); // Set analog reference to 1.1V
analogRead(VccPin); //discard first analogRead
pinMode(ActivePin, OUTPUT); // Set for output

SPI.begin();
radio.begin();
network.begin(channel, this_node);

// Power down the radio. Note that the radio will get powered back up on the next write() call.
radio.powerDown();
}

void loop(void){
// Pump the network regularly
network.update();
getVoltage();
getStats();
sendPayload();
delay(sleepDelay);
//Narcoleptic.delay(sleepDelay); // During this time power consumption is minimized
}

void getStats() {
//Pull data from DHT11
//Set variables to inputs
humid = dht.readHumidity();
temp = dht.readTemperature(true);
//If variables are empty
//print failed to read
//if (isnan(temp) || isnan(humid)) {
// Serial.println("Failed to read DHT");
//}
//Serial.print("Humidity: ");
//Serial.print(humid);
//Serial.print(", Temp: ");
//Serial.println(temp);
}

//////////////////////////////////////////////////////////////////////////////////
// Read analog input for VccPin averaged over NUM_SAMPLES
// Uses a running average
// Vcc is scaled with a voltage divider * 75K/(75K + 240K) so reverse
// Should be 4.2, try 3.9
//////////////////////////////////////////////////////////////////////////////////
void getVoltage(){
const byte NUM_SAMPLES = 20;
float SumTotal=0;
for (byte j=0;j<NUM_SAMPLES;j++){
SumTotal+= analogRead(VccPin);
delay(10);
}
Vcc = ((SumTotal/NUM_SAMPLES)*1.1/1023.0)*3.9;
}
//////////////////////////////////////////////////////////////////////////////////
// sendPayload(); // send payload
//////////////////////////////////////////////////////////////////////////////////
void sendPayload(){
digitalWrite(ActivePin, HIGH); // Turn on LED
payload_t payload = { packets_sent++, humid, temp, Vcc };
RF24NetworkHeader header(/*to node*/ other_node);
bool ok = network.write(header,&payload,sizeof(payload));
// Power down the radio. Note that the radio will get powered back up on the next write() call.
radio.powerDown();
digitalWrite(ActivePin, LOW); // Turn off LED
}