Skip to content
Snippets Groups Projects
Commit 99d98039 authored by smurray798's avatar smurray798
Browse files

Updated node code to send packets

parent f3fd82b0
Branches
No related tags found
No related merge requests found
......@@ -15,6 +15,40 @@
#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
#include <TemperatureZero.h>
/** Defines **/
#define NODE_ID 1
#define NETWORK_FREQUENCY 914
// clock parameters
#define CPU_HZ 48000000
#define TIMER_PRESCALER_DIV 1024
// Error codes
#define ERROR_CODE_MISSING_PACKET 0x01
#define ERROR_CODE_RECEPTION_FAILURE 0x02
#define ERROR_CODE_WDT_EARLY_WARNING 0x04
#define ERROR_CODE_INVALID_TEMPERATURE 0x08
#define ERROR_CODE_MISMATCHED_PACKET_NUM 0x10
/** Type Definitions **/
typedef struct
{
uint8_t NodeID;
uint16_t PacketID;
uint32_t Timestamp;
float AverageTemperature;
uint8_t ErrorType;
} Lab3Packet_t;
/** Static Variables **/
static TemperatureZero TempZero = TemperatureZero();
static float g_temperature_samples[5];
static float g_temperature_samples_count = 0;
static int32_t initialMillis = 0;
static volatile Lab3Packet_t txPacket;
static volatile unsigned int counterISR = 1;
// we formerly would check this configuration; but now there is a flag,
// in the LMIC, LMIC.noRXIQinversion;
......@@ -49,17 +83,14 @@ const lmic_pinmap lmic_pins = {
void os_getArtEui (u1_t* buf) { }
void os_getDevEui (u1_t* buf) { }
void os_getDevKey (u1_t* buf) { }
void onEvent (ev_t ev)
{
}
void onEvent (ev_t ev) { }
osjob_t txjob;
osjob_t timeoutjob;
static void tx_func (osjob_t* job);
// Transmit the given string and call the given function afterwards
/*
void tx(const char *str, osjobcb_t func)
{
os_radio(RADIO_RST); // Stop RX first
......@@ -71,6 +102,21 @@ void tx(const char *str, osjobcb_t func)
os_radio(RADIO_TX);
SerialUSB.println("TX");
}
*/
void tx(const void* msg, uint8_t len, osjobcb_t func)
{
os_radio(RADIO_RST); // Stop RX first
delay(1); // Wait a bit, without this os_radio below asserts, apparently because the state hasn't changed yet
LMIC.dataLen = len;
uint16_t i;
for (i = 0; i < len; i++)
{
LMIC.frame[i] = *(((uint8_t*)msg) + i);
}
LMIC.osjob.func = func;
os_radio(RADIO_TX);
SerialUSB.println("TX");
}
// Enable rx mode and call func when a packet is received
void rx(osjobcb_t func)
......@@ -96,14 +142,31 @@ static void rx_func (osjob_t* job)
digitalWrite(LED_BUILTIN, HIGH); // on
// Timeout RX (i.e. update led status) after 3 periods without RX
os_setTimedCallback(&timeoutjob, os_getTime() + ms2osticks(3*TX_INTERVAL), rxtimeout_func);
// Reschedule TX so that it should not collide with the other side's
// next TX
// Reschedule TX so that it should not collide with the other side's next TX
os_setTimedCallback(&txjob, os_getTime() + ms2osticks(TX_INTERVAL / 2), tx_func);
SerialUSB.print("Got ");
SerialUSB.print(LMIC.dataLen);
SerialUSB.println(" bytes");
SerialUSB.write(LMIC.frame, LMIC.dataLen);
SerialUSB.println();
// Print the received output
if (LMIC.dataLen != sizeof(Lab3Packet_t))
{
SerialUSB.println("Error: improper RX packet size.");
}
else
{
Lab3Packet_t* packet = (Lab3Packet_t*)LMIC.frame;
if (initialMillis == 0)
{
initialMillis = millis() - packet->Timestamp;
}
printPacket(packet);
}
//SerialUSB.print("Got ");
//SerialUSB.print(LMIC.dataLen);
//SerialUSB.println(" bytes");
//SerialUSB.write(LMIC.frame, LMIC.dataLen);
//SerialUSB.println();
// Restart RX
rx(rx_func);
}
......@@ -117,7 +180,22 @@ static void txdone_func (osjob_t* job)
static void tx_func (osjob_t* job)
{
// say hello
tx("Hello, world!", txdone_func);
//tx("Hello, world!", txdone_func);
// Construct packet
constructTxPacket((Lab3Packet_t*)&txPacket);
// Send the packet
tx((Lab3Packet_t*)&txPacket, sizeof(txPacket), txdone_func);
// Print the packet
printPacket((Lab3Packet_t*)&txPacket);
IsErrorDetect((Lab3Packet_t*)&txPacket);
// Set up the next packet's packet ID
txPacket.PacketID++;
txPacket.ErrorType = 0;
// reschedule job every TX_INTERVAL (plus a bit of random to prevent systematic collisions), unless packets are received, then rx_func will reschedule at half this time.
os_setTimedCallback(job, os_getTime() + ms2osticks(TX_INTERVAL + random(500)), tx_func);
}
......@@ -125,10 +203,18 @@ static void tx_func (osjob_t* job)
// application entry point
void setup()
{
// Initialize temperature readings, start timer that gets temperature samples
TempZero.init();
startTimer(1);
// Initialize Serial USB interface
SerialUSB.begin(115200);
while (!SerialUSB); // wait for Serial Monitor to be attached to SparkFun Pro RF board
SerialUSB.println("Starting");
// Initialize transmit packet
initPacket((Lab3Packet_t*)&txPacket);
pinMode(LED_BUILTIN, OUTPUT);
// initialize runtime env
os_init();
......@@ -137,7 +223,7 @@ void setup()
uint32_t uBandwidth;
LMIC.freq = 915000000; // originally was 903900000 in the example
uBandwidth = 125;
LMIC.datarate = US915_DR_SF10; // DR4, originally was US915_DR_SF7 in the example
LMIC.datarate = US915_DR_SF7; // DR4
LMIC.txpow = 20; // originally was 21 in the example
// disable RX IQ inversion
......@@ -168,3 +254,213 @@ void loop()
// execute scheduled jobs and events
os_runloop_once();
}
/** Function Definitions **/
int getNewTemperatureSample()
{
// Returns 0 if new temperature sample is valid, returns -1 if not
float temperature = TempZero.readInternalTemperature();
SerialUSB.print("Temp = ");
SerialUSB.println(temperature);
// Is this a valid temperature?
if ((temperature >= 0.1) && (temperature <= 100.0))
{
// This is a valid temperature
// Shift over the sample buffer
int i;
for (i = 4; i > 0; i--)
{
g_temperature_samples[i] = g_temperature_samples[i - 1];
}
// Put the new temperature in the sample buffer
g_temperature_samples[0] = temperature;
// If the sample buffer is not full, increment the number of samples in it
if (g_temperature_samples_count < 5)
{
g_temperature_samples_count++;
}
return 0;
}
else
{
return -1;
}
}
float getAverageTemperature()
{
// Returns the average temperature if there are 5 valid temperature samples in the buffer, returns NAN otherwise
if (g_temperature_samples_count == 5)
{
// Calculate average
float sum = 0;
int i;
for (i = 0; i < 5; i++)
{
sum += g_temperature_samples[i];
}
return sum / 5.0;
}
else
{
return NAN;
}
}
void initPacket(Lab3Packet_t* packet)
{
packet->NodeID = NODE_ID;
packet->PacketID = 1;
packet->Timestamp = 0;
packet->AverageTemperature = 0;
packet->ErrorType = 0x00;
}
String packetToString(Lab3Packet_t* packet, bool printThisDeviceTag)
{
String s = String("Node ID = ")
+ String(packet->NodeID)
+ String(", Packet ID = ")
+ String(packet->PacketID)
+ String(", Timestamp = ")
+ String(packet->Timestamp)
+ String(", Average Temperature = ")
+ String(packet->AverageTemperature)
+ String(", Error Type = 0x")
+ String(packet->ErrorType, HEX)
;
if (printThisDeviceTag && (packet->NodeID == NODE_ID))
{
s += String(" (this device)");
}
return s;
}
void printPacket(Lab3Packet_t* packet)
{
SerialUSB.println(packetToString(packet, true));
}
void constructTxPacket(Lab3Packet_t* packet_out)
{
// Assumes that you have added all the errors to packet->ErrorType before calling this function
// Get the average temperature
float averageTemperature = getAverageTemperature();
if ((averageTemperature != averageTemperature) || (averageTemperature > 60) || (averageTemperature < 0))
{
packet_out->ErrorType |= ERROR_CODE_INVALID_TEMPERATURE;
}
// Populate packet with data
packet_out->Timestamp = millis() - initialMillis;
packet_out->AverageTemperature = averageTemperature;
return;
}
void setTimerFrequency(int frequencyHz)
{
int compareValue3 = (CPU_HZ / (TIMER_PRESCALER_DIV * frequencyHz)) - 1;
TcCount16* TC4p = (TcCount16*) TC4;
// Make sure the count is in a proportional position to where it was
// to prevent any jitter or disconnect when changing the compare value.
TC4p->COUNT.reg = map(TC4p->COUNT.reg, 0, TC4p->CC[0].reg, 0, compareValue3);
TC4p->CC[0].reg = compareValue3;
while (TC4p->STATUS.bit.SYNCBUSY == 1);
}
void startTimer(int frequencyHz)
{
REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN |
GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_TC4_TC5) ;
while ( GCLK->STATUS.bit.SYNCBUSY == 1 ); // wait for sync
TcCount16* TC4p = (TcCount16*) TC4;
TC4p->CTRLA.reg &= ~TC_CTRLA_ENABLE; //Disable timer
TC4p->CTRLA.reg |= TC_CTRLA_MODE_COUNT16 | TC_CTRLA_WAVEGEN_MFRQ | TC_CTRLA_PRESCALER_DIV1024;
while (TC4p->STATUS.bit.SYNCBUSY == 1); // wait for sync
setTimerFrequency(1);
TC4p->INTENSET.reg = 0;
TC4p->INTENSET.bit.OVF = 1;
NVIC_EnableIRQ(TC4_IRQn);
TC4p->CTRLA.reg |= TC_CTRLA_ENABLE;
while (TC4p->STATUS.bit.SYNCBUSY == 1); // wait for sync
}
bool IsErrorDetect(Lab3Packet_t* packet)
{
if (packet->ErrorType == 0)
{
return false;
}
uint32_t errorCode = 0
| ((uint32_t)packet->ErrorType) << 24 // ErrorType occupies bits 31 downto 24
| ((uint32_t)packet->NodeID) << 16 // NodeID occupies bits 23 downto 16
| ((uint32_t)packet->PacketID) // PacketID occupies bits 15 downto 0
;
// Print an error message
printError(errorCode);
return true;
}
void printError(uint32_t errorCode)
{
uint8_t errorType = errorCode >> 24;
uint8_t nodeID = errorCode >> 16;
uint16_t packetID = errorCode;
SerialUSB.print("Error(s) on Node ID ");
SerialUSB.print(": ");
if (errorType == 0)
{
SerialUSB.println("No errors");
return;
}
SerialUSB.print("Error(s): ");
if (errorType & ERROR_CODE_MISSING_PACKET)
{
SerialUSB.print("{Missing packet} ");
}
if (errorType & ERROR_CODE_RECEPTION_FAILURE)
{
SerialUSB.print("{Reception failure} ");
}
if (errorType & ERROR_CODE_WDT_EARLY_WARNING)
{
SerialUSB.print("{WDT early warning} ");
}
if (errorType & ERROR_CODE_INVALID_TEMPERATURE)
{
SerialUSB.print("{Invalid temperature} ");
}
SerialUSB.println("");
}
/** ISRs **/
void TC4_Handler()
{
TcCount16* TC4p = (TcCount16*) TC4;
// If this interrupt is due to the compare register matching the timer count
// we toggle the LED.
if (TC4p->INTFLAG.bit.OVF == 1)
{
TC4p->INTFLAG.bit.OVF = 1;
// Write callback here!!!
// This handler executes every 1.0 seconds to measure the temperature and add it to the moving average
getNewTemperatureSample();
// five second block counter
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment