Gbox 4.20
Grow box automation and monitoring - <a href='https://sites.google.com/site/growboxguy/'>https://sites.google.com/site/growboxguy/</a>
 
Loading...
Searching...
No Matches
Gbox420_Nano_Reservoir.ino
Go to the documentation of this file.
1
10#include "Arduino.h"
11#include "avr/wdt.h" // Watchdog timer for detecting a crash and automatically resetting the board
12#include "avr/boot.h" // Watchdog timer related bug fix
13#include "printf.h"
14#include "Thread.h" // Splitting functions to threads for timing
15#include "StaticThreadController.h" // Grouping threads
16#include "SPI.h" // allows you to communicate with SPI devices, with the Arduino as the master device
17#include "RF24.h" // https://github.com/maniacbug/RF24
18#include "SerialLog.h" // Logging debug messages to Serial
19#include "Settings.h"
20#include "src/Modules/ReservoirModule.h"
21#include "src/WirelessCommands_Reservoir.h" // Structs for wireless communication via the nRF24L01 chip, defines the messages exchanged with the main modul
22
23// Global variable initialization
24bool &Debug = *new bool;
25bool &Metric = *new bool;
26char LongMessage[MaxLongTextLength] = ""; // Temp storage for assembling long messages (REST API - Google Sheets reporting)
27char ShortMessage[MaxShotTextLength] = ""; // Temp storage for assembling short messages (Log entries, Error messages)
28char CurrentTime[MaxWordLength] = ""; // Buffer for storing current time in text format
29void *ReceivedMessage = malloc(WirelessPayloadSize); // Stores a pointer to the latest received data. A void pointer is a pointer that has no associated data type with it. A void pointer can hold address of any type and can be typcasted to any type. Malloc allocates a fixed size memory section and returns the address of it.
30uint32_t ReceivedMessageTimestamp = millis(); // Stores the timestamp when the last wireless package was received
31
32// Component initialization
33HardwareSerial &ArduinoSerial = Serial; // Reference to the Arduino Serial
34Settings *ModuleSettings; // settings loaded from the EEPROM. Persistent between reboots, defaults are in Settings.h
35ReservoirModule *ReservoirMod1; // Represents a Reservoir tote with temp,PH,water level sensors
36RF24 Wireless(WirelessCEPin, WirelessCSNPin); // Initialize the NRF24L01 wireless chip (CE, CSN pins are hard wired on the Arduino Nano RF)
37
38// Thread initialization
39Thread OneSecThread = Thread();
40Thread FiveSecThread = Thread();
41Thread MinuteThread = Thread();
42StaticThreadController<3> ThreadControl(&OneSecThread, &FiveSecThread, &MinuteThread);
43
44void setup()
45{ // put your setup code here, to run once:
46 ArduinoSerial.begin(115200); // Nano console output
47 printf_begin();
48 logToSerials(F(""), true, 0); // New line
49 logToSerials(F("Reservoir module initializing"), true, 0); // logs to the Arduino serial, adds new line after the text (true), and uses no indentation (0). More on why texts are in F(""): https:// gist.github.com/sticilface/e54016485fcccd10950e93ddcd4461a3
50 wdt_enable(WDTO_8S); // Watchdog timeout set to 8 seconds, if watchdog is not reset every 8 seconds it assumes a lockup and resets the sketch
51 boot_rww_enable(); // fix watchdog not loading sketch after a reset error on Mega2560
52 struct ReservoirModuleCommand BlankCommand = {ReservoirMessages::ReservoirModuleCommand1};
53 memcpy(ReceivedMessage, &BlankCommand, sizeof(struct ReservoirModuleCommand)); // Copy a blank command to the memory block pointed ReceivedMessage. Without this ReceivedMessage would contain random data
54 setSyncProvider(updateTime);
55 setSyncInterval(3600); // Sync time every hour with the main module
56
57 // Loading settings from EEPROM
61
62 // Setting up wireless module
64
65 // Threads - Setting up how often threads should be triggered and what functions to call when the trigger fires
66 OneSecThread.setInterval(1000); // 1000ms
67 OneSecThread.onRun(run1sec);
68 FiveSecThread.setInterval(5000);
70 MinuteThread.setInterval(60000);
71 MinuteThread.onRun(run1min);
72
73 // Create the Reservoir Module object
74 ReservoirMod1 = new ReservoirModule(F("Res1"), &ModuleSettings->Res1); // This is the main object representing an entire Grow Box with all components in it. Receives its name and the settings loaded from the EEPROM as parameters
75
76 logToSerials(F("Setup ready, starting loops:"), true, 0);
77}
78
80{
81 logToSerials(F("(re)Initializing wireless transceiver"), false, 0);
82 pinMode(WirelessCSNPin, OUTPUT);
83 digitalWrite(WirelessCSNPin, HIGH);
84 pinMode(WirelessCEPin, OUTPUT);
85 digitalWrite(WirelessCEPin, HIGH);
86 Wireless.begin();
87 Wireless.powerDown();
88 Wireless.setDataRate(RF24_250KBPS);
89 Wireless.setCRCLength(RF24_CRC_16);
90 Wireless.setPALevel(RF24_PA_MAX);
91 Wireless.setPayloadSize(WirelessPayloadSize);
92 Wireless.enableDynamicPayloads();
93 Wireless.enableAckPayload();
94 Wireless.openReadingPipe(1, WirelessChannel);
95 Wireless.startListening();
96 Wireless.powerUp();
97 Wireless.flush_tx();
98 Wireless.flush_rx();
99 logToSerials(F("done"), true, 3);
100 ReceivedMessageTimestamp = millis();
101}
102
103void loop()
104{ // put your main code here, to run repeatedly:
105 ThreadControl.run(); // loop only checks if it's time to trigger one of the threads (run1sec(), run5sec(),run1min()..etc)
106 // If a control package is received from the main module
108}
109
110// Threads
111
113{
114 wdt_reset();
115 ReservoirMod1->run1sec(); // Calls the run1sec() method in GrowBox.cpp
116}
117
119{
120 wdt_reset();
121 ReservoirMod1->run5sec();
122}
123
125{
126 wdt_reset();
127 ReservoirMod1->run1min();
128 //getWirelessStatus(); //USES TOO MUCH MEMORY!
129}
130
131// Wireless communication
132
134{
135 if (Wireless.available())
136 {
138 if (timeStatus() != timeSet && ((ReservoirCommonTemplate *)ReceivedMessage)->SequenceID == ReservoirMessages::ReservoirModuleCommand1)
139 {
140 updateTime(); // Updating internal timer
141 }
142 if (ReservoirMod1->processCommand(ReceivedMessage))
143 {
144 ReceivedMessageTimestamp = millis(); //< Reset the timer after the last message was exchanged
145 }
146 }
148 {
150 }
151}
152
154{
155 if (Debug)
156 {
157 logToSerials(F("Wireless report:"), true, 0);
158 Wireless.printPrettyDetails();
159 logToSerials(F(""), true, 0); // Just a line break after the report
160 }
161}
162
164{
165 time_t ReceivedTime = ((ReservoirModuleCommand *)ReceivedMessage)->Time;
166 if (ReceivedTime > 0)
167 {
168 setTime(ReceivedTime);
169 logToSerials(F("Clock synced"), true, 0);
170 }
171 else
172 {
173 logToSerials(F("Clock out of sync"), true, 0);
174 }
175 return ReceivedTime;
176}
void logToSerials(const __FlashStringHelper *ToPrint, bool BreakLine, uint8_t Indent)
< Logging
Definition SerialLog.cpp:5
Settings * loadSettings(bool ResetEEPROM)
Load settings from EEPROM.
Definition Settings.cpp:20
constexpr uint8_t WirelessPayloadSize
Size of the wireless packages exchanged with the Main module. Max 32 bytes are supported on nRF24L01+...
Definition Settings.h:31
constexpr uint8_t WirelessCEPin
nRF24l01+ wireless transmitter CE pin - Pre-connected on RF-Nano
Definition Settings.h:29
constexpr uint8_t MaxShotTextLength
Default char * buffer length for storing mutiple words. Memory intense!
Definition Settings.h:18
constexpr uint8_t MaxWordLength
Default char * buffer length for storing a word + null terminator. Memory intense!
Definition Settings.h:17
constexpr uint16_t MaxLongTextLength
Default char * buffer length for storing a long text. Memory intense!
Definition Settings.h:19
constexpr uint16_t WirelessReceiveTimeout
(ms) If no packages are received from the Main module over this limit, try reseting the nRF24L01+ wir...
Definition Settings.h:33
constexpr uint8_t WirelessCSNPin
< nRF24L01+ wireless receiver
Definition Settings.h:28
constexpr uint8_t WirelessChannel[6]
This needs to be unique and match with the Name of the HempyModule_Web object in the MainModule_Web....
Definition Settings.h:30
void run5sec()
void getWirelessData()
Thread OneSecThread
RF24 Wireless(WirelessCEPin, WirelessCSNPin)
ReservoirModule * ReservoirMod1
char CurrentTime[MaxWordLength]
Buffer for storing current time in text format.
char LongMessage[MaxLongTextLength]
Temp storage for assembling long messages (REST API, MQTT reporting)
Thread MinuteThread
uint32_t ReceivedMessageTimestamp
void setup()
Thread FiveSecThread
char ShortMessage[MaxShotTextLength]
Temp storage for assembling short text messages (Log entries, Error messages,etc)
void run1min()
time_t updateTime()
void InitializeWireless()
Settings * ModuleSettings
HardwareSerial & ArduinoSerial
Printing serial messages to the Arduino Serial output and the esp-link Microcontroller Console (uC Co...
bool & Debug
void * ReceivedMessage
bool & Metric
void run1sec()
void getWirelessStatus()
struct ReservoirModuleSettings Res1
Definition Settings.h:53
bool Metric
Switch between Imperial/Metric units. If changed update the default temp and pressure values below to...
Definition Settings.h:61
bool Debug
Logs debug messages to serial and web outputs.
Definition Settings.h:60