Trying to use DHT11 with a PxMatrix display on ESP32 board - c++

I'm trying to display the readings from a DHT11 onto an LED Matrix. I can get the basic display to work, the issue is when I also put the time on the display. I started with the Morphing Clock as a base for the time then used the Adafruit Sensor code to read the DHT11. The issue seems to be with"
timerAlarmWrite(timer, 2000, true);
Which is setup to call:
void IRAM_ATTR display_updater(){
// Increment the counter and set the time of ISR
portENTER_CRITICAL_ISR(&timerMux);
display.display(10);
portEXIT_CRITICAL_ISR(&timerMux);
}
If I slow the timer down I can get readings from the DHT11 but the morphing time display doesn't update enough to look fluid. I'm new to coding for these devices so I'm not sure where I should be looking to move these things out of each others way. Here is the full app if the timer is set to something above 25000 you will get temp results most of the time, but the less are dimmer and the colons flash (they shouldn't).
#define double_buffer
#include <PxMatrix.h>
#include <WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include "Digit.h"
#include <Adafruit_Sensor.h>
#include <DHT.h>
const char* ssid = "Gallifrey";
const char* password = "ThisIsAGoodPlaceToPutAPassword!";
// ESP32 Pins for LED MATRIX
#define P_LAT 22
#define P_A 19
#define P_B 23
#define P_C 18
#define P_D 5
#define P_E 15 // NOT USED for 1/16 scan
#define P_OE 2
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
PxMATRIX display(64,32,P_LAT, P_OE,P_A,P_B,P_C,P_D,P_E);
void IRAM_ATTR display_updater(){
// Increment the counter and set the time of ISR
portENTER_CRITICAL_ISR(&timerMux);
display.display(10);
portEXIT_CRITICAL_ISR(&timerMux);
}
// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
// Variables to save date and time
String formattedDate;
String dayStamp;
String timeStamp;
unsigned long prevEpoch;
byte prevhh;
byte prevmm;
byte prevss;
//====== Digits =======
Digit digit0(&display, 0, 63 - 1 - 9*1, 17, display.color565(0, 250, 0));
Digit digit1(&display, 0, 63 - 1 - 9*2, 17, display.color565(0, 250, 0));
Digit digit2(&display, 0, 63 - 4 - 9*3, 17, display.color565(0, 250, 0));
Digit digit3(&display, 0, 63 - 4 - 9*4, 17, display.color565(0, 250, 0));
Digit digit4(&display, 0, 63 - 7 - 9*5, 17, display.color565(0, 250, 0));
Digit digit5(&display, 0, 63 - 7 - 9*6, 17, display.color565(0, 250, 0));
#define DHTPIN 27
#define DHTTYPE DHT11
//DHT_Unified dht(DHTPIN, DHTTYPE);
DHT dht(DHTPIN, DHTTYPE);
//DHT dht;
const uint32_t delayMS = 6000;
uint32_t lastRead;
void setup() {
display.begin(16); // 1/16 scan
display.setFastUpdate(true);
// Initialize Serial Monitor
Serial.begin(115200);
pinMode(DHTPIN, INPUT_PULLUP);
dht.begin();
// // Set delay between sensor readings based on sensor details.
lastRead = 0;
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &display_updater, true);
timerAlarmWrite(timer, 1500, true); /// The Problem is Here!!!???!!!!?
timerAlarmEnable(timer);
display.fillScreen(display.color565(0, 0, 0));
digit1.DrawColon(display.color565(100, 175, 0));
digit3.DrawColon(display.color565(100, 175, 0));
// Print local IP address and start web server
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// Initialize a NTPClient to get time
timeClient.begin();
timeClient.setTimeOffset(-28800);
}
void loop() {
while(!timeClient.update()) {
timeClient.forceUpdate();
}
formattedDate = timeClient.getFormattedDate();
// Extract date
int splitT = formattedDate.indexOf("T");
dayStamp = formattedDate.substring(0, splitT);
// Extract time
timeStamp = formattedDate.substring(splitT+1, formattedDate.length()-1);
displayLocalTemp();
updateTimeDisplay();
}
String readDHTTemperature() {
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
// Read temperature as Celsius (the default)
float t = dht.readTemperature(true);
// Read temperature as Fahrenheit (isFahrenheit = true)
//float t = dht.readTemperature(true);
// Check if any reads failed and exit early (to try again).
if (isnan(t)) {
Serial.println("Failed to read from DHT sensor!");
return "--";
}
else {
Serial.println(t);
return String(t);
}
}
String readDHTHumidity() {
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h = dht.readHumidity();
if (isnan(h)) {
Serial.println("Failed to read from DHT sensor!");
return "--";
}
else {
Serial.println(h);
return String(h);
}
}
void displayLocalTemp() {
uint32_t currentTime = millis();
uint32_t waited = currentTime - lastRead;
static String lastTemp;
static String lastHumid;
if (waited > delayMS) {
lastRead = currentTime;
String temp = readDHTTemperature();
String humidity = readDHTHumidity();
String preTemp = "T:";
String preHumidity = "H:";
String tempDisplay = preTemp + temp;
String humidDisplay = preHumidity + humidity;
Serial.print("temp: ");
Serial.print(temp);
Serial.print(" -- humidity: ");
Serial.println(humidity);
display.setTextColor(display.color565(0,0,0));
display.setCursor(20,16);
display.print(lastTemp);
display.setCursor(20,25);
display.print(lastHumid);
display.setTextColor(display.color565(0,255,0));
display.setCursor(20,16);
display.print(tempDisplay);
display.setCursor(20,25);
display.print(humidDisplay);
lastTemp = tempDisplay;
lastHumid = humidDisplay;
}
}
void updateTimeDisplay() {
unsigned long epoch = timeClient.getEpochTime();
if (epoch != prevEpoch) {
int hh = timeClient.getHours();
int mm = timeClient.getMinutes();
int ss = timeClient.getSeconds();
if (hh > 12) hh = hh % 12;
if (prevEpoch == 0) { // If we didn't have a previous time. Just draw it without morphing.
digit0.Draw(ss % 10);
digit1.Draw(ss / 10);
digit2.Draw(mm % 10);
digit3.Draw(mm / 10);
digit4.Draw(hh % 10);
digit5.Draw(hh / 10);
}
else
{
// epoch changes every miliseconds, we only want to draw when digits actually change.
if (ss!=prevss) {
int s0 = ss % 10;
int s1 = ss / 10;
if (s0!=digit0.Value()) digit0.Morph(s0);
if (s1!=digit1.Value()) digit1.Morph(s1);
//ntpClient.PrintTime();
prevss = ss;
}
if (mm!=prevmm) {
int m0 = mm % 10;
int m1 = mm / 10;
if (m0!=digit2.Value()) digit2.Morph(m0);
if (m1!=digit3.Value()) digit3.Morph(m1);
prevmm = mm;
}
if (hh!=prevhh) {
int h0 = hh % 10;
int h1 = hh / 10;
if (h0!=digit4.Value()) digit4.Morph(h0);
if (h1!=digit5.Value()) digit5.Morph(h1);
prevhh = hh;
}
}
prevEpoch = epoch;
}
}

You could try to assign tasks explicitly to a core.
When you start playing with ESP32 multi core code execution be aware of the following issues:
Both the setup and the main loop functions execute with a priority of 1.
Arduino main loop runs on core 1.
The execution is pinned, so it’s not expected that the core will change during execution of the program
On FreeRTOS (the underlying OS), tasks have an assigned priority which the scheduler uses to decide which task will run.
High priority tasks ready to run will have preference over lower priority tasks, which means that as long as a higher priority task can run, a lower priority task will not have the CPU.
CAUTION shared resources like Serial might be potential issues. Due to two core tasks accessing uncoordinated the same hardware may lead to deadlocks and crashes
For implementation purposes, you need to take in consideration that FreeRTOS priorities are assigned from 0 to N, where lower numbers correspond to lower priorities. So, the lowest priority is 0.
First of all, declare a global variable that will contain the number of the core where the FreeRTOS task to launch will be pinned
static int taskCore = 0; // The core the task should run on
now create the assignment of a task to the core in Setup()
xTaskCreatePinnedToCore(
myCoreTask, /* Function to implement the task */
"myCoreTask", /* Name of the task */
10000, /* Stack size in words */
NULL, /* Task input parameter */
0, /* Priority of the task */
NULL, /* Task handle. */
taskCore); /* Core where the task should run */
Here is a test function which you call in loop()
void myCoreTask( void * pvParameters ){
while(true){
Serial.println("Task running on core ");
Serial.print(xPortGetCoreID());
// This is here to show that other tasks run
// NEVER use in production
delay(1000);
}
}
Hope this gives you an idea how to tackle your problem, read more here RTOS and here ESP32-IDF

Related

How to read motor encoder values with interrupts in FreeRTOS?

I am working on a project where I need to obtain precise angular velocity from four motor encoders. I am using ESP32 DEVKIT-V1 module, and would like to use four interrupts, which will fire when each motor encoder switches state. This produces a square signal of around 700 Hz (period of 1,42 ms). This needs to be done on one core due to timing restrictions, as the processor must not miss any ticks. This is why I decided to use FreeRTOS. As the tick rate of the ESP32 is 1 ms, it cannot read higher frequencies than 500 Hz (period of 2 ms).
I would like to call getEncoderTickNumber() function every time one of the four interrupts fires, however, I only get the ESP32 to continually reset. I also wish to pass the number of ticks (encoderValueA1 - A4) from function getEncoderTickNumber() to getEncoderRPM() by queues.
I am still a beginner in C/C++, so I would be very grateful if you could point out some beginner mistakes that I am making. Thank you for your time.
#include <Arduino.h>
// Motor encoder output pulse per rotation (AndyMark Neverest 60)
int ENC_COUNT_REV = 420;
// Pulse count from encoder
long encoderValueA1 = 0;
long encoderValueA2 = 0;
long encoderValueA3 = 0;
long encoderValueA4 = 0;
int currentStateMotorEncoderA1;
int currentStateMotorEncoderA2;
int currentStateMotorEncoderA3;
int currentStateMotorEncoderA4;
int previousStateMotorEncoderA1;
int previousStateMotorEncoderA2;
int previousStateMotorEncoderA3;
int previousStateMotorEncoderA4;
// Variable for RPM measuerment
int rpm1 = 0;
int rpm2 = 0;
int rpm3 = 0;
int rpm4 = 0;
#define INT_PIN1 17
#define INT_PIN2 18
#define INT_PIN3 19
#define INT_PIN4 16
#define PRIORITY_LOW 0
#define PRIORITY_HIGH 1
QueueHandle_t encoderQueueHandle;
#define QUEUE_LENGTH 4 //four rpm readings
long* pdata = &encoderValueA1;
void io_expander_interrupt()
{
xQueueSendToBackFromISR(&encoderQueueHandle, &pdata, NULL);
}
///////////
// TASKS //
///////////
void getEncoderTickNumber(void *parameter)
{
while (1)
{
if (xQueueReceiveFromISR(&encoderQueueHandle, &pdata, NULL) == pdTRUE)
{
currentStateMotorEncoderA1 = digitalRead(INT_PIN1);
currentStateMotorEncoderA2 = digitalRead(INT_PIN2);
currentStateMotorEncoderA3 = digitalRead(INT_PIN3);
currentStateMotorEncoderA4 = digitalRead(INT_PIN4);
if (currentStateMotorEncoderA1 != previousStateMotorEncoderA1)
{
encoderValueA1++;
}
if (currentStateMotorEncoderA2 != previousStateMotorEncoderA2)
{
encoderValueA2++;
}
if (currentStateMotorEncoderA3 != previousStateMotorEncoderA3)
{
encoderValueA3++;
}
if (currentStateMotorEncoderA4 != previousStateMotorEncoderA4)
{
encoderValueA4++;
}
previousStateMotorEncoderA1 = currentStateMotorEncoderA1;
previousStateMotorEncoderA2 = currentStateMotorEncoderA2;
previousStateMotorEncoderA3 = currentStateMotorEncoderA3;
previousStateMotorEncoderA4 = currentStateMotorEncoderA4;
}
}
}
void getEncoderRPM(void *parameter)
{
while (1)
{
rpm1 = (encoderValueA1 * 60) / ENC_COUNT_REV;
rpm2 = (encoderValueA2 * 60) / ENC_COUNT_REV;
rpm3 = (encoderValueA3 * 60) / ENC_COUNT_REV;
rpm4 = (encoderValueA4 * 60) / ENC_COUNT_REV;
encoderValueA1 = 0;
encoderValueA2 = 0;
encoderValueA3 = 0;
encoderValueA4 = 0;
vTaskDelay(1000 / portTICK_RATE_MS);
}
}
void printData(void *parameter)
{
while (1)
{
Serial.print("1:");
Serial.print(rpm1);
Serial.print(" 2:");
Serial.print(rpm2);
Serial.print(" 3:");
Serial.print(rpm3);
Serial.print(" 4:");
Serial.println(rpm4);
vTaskDelay(500 / portTICK_RATE_MS);
}
}
void setup()
{
Serial.begin(115200);
pinMode(INT_PIN1, INPUT);
attachInterrupt(INT_PIN1, getEncoderTickNumber, RISING);
pinMode(INT_PIN2, INPUT);
attachInterrupt(INT_PIN2, getEncoderTickNumber, RISING);
pinMode(INT_PIN3, INPUT);
attachInterrupt(INT_PIN3, getEncoderTickNumber, RISING);
pinMode(INT_PIN4, INPUT);
attachInterrupt(INT_PIN4, getEncoderTickNumber, RISING);
// Create the queue
encoderQueueHandle = xQueueCreate(QUEUE_LENGTH, sizeof(uint32_t));
xTaskCreatePinnedToCore( // Use xTaskCreate() in vanilla FreeRTOS
getEncoderTickNumber, // Function to be called
"getEncoderTickNumber", // Name of task
1024, // Stack size (bytes in ESP32, words in FreeRTOS) inside the heap
NULL, // Parameter to pass to function
PRIORITY_LOW, // Task priority (0 to configMAX_PRIORITIES - 1)
NULL, // Task handle
1); // Run on one core for demo purposes (ESP32 only)
xTaskCreatePinnedToCore( // Use xTaskCreate() in vanilla FreeRTOS
printData, // Function to be called
"printData", // Name of task
1024, // Stack size (bytes in ESP32, words in FreeRTOS) inside the heap
NULL, // Parameter to pass to function
PRIORITY_LOW, // Task priority (0 to configMAX_PRIORITIES - 1)
NULL, // Task handle
0); // Run on one core for demo purposes (ESP32 only)
xTaskCreatePinnedToCore( // Use xTaskCreate() in vanilla FreeRTOS
getEncoderRPM, // Function to be called
"getEncoderRPM", // Name of task
1024, // Stack size (bytes in ESP32, words in FreeRTOS)
NULL, // Parameter to pass to function
PRIORITY_HIGH, // Task priority (0 to configMAX_PRIORITIES - 1)
NULL, // Task handle
0); // Run on one core for demo purposes (ESP32 only)
vTaskDelete(NULL); // Deletes the setup/loop task now that we are finished setting up (optional)
}
void loop()
{
}
There are quite a few problems in your code. Let's go over them one by one, see if it clears things up.
Firstly, don't delete the task in setup():
vTaskDelete(NULL); // Deletes the setup/loop task now that we are finished setting up (optional)
Arduino will manage the FreeRTOS tasks on its own, don't interfere with it. You may be causing your crash with that line alone.
Secondly, you're creating your tasks with a stack size of 1024 bytes which is too small. The task will likely corrupt the stack and crash. Start with a stack size of 4096 bytes for simple tasks, see if you can optimize later. Incidentally, you don't need any tasks at all for a simple implementation.
Thirdly, you don't seem to understand what an interrupt is and how to handle it. By calling this you're attaching the function getEncoderTickNumber() as an interrupt handler to all 4 GPIO inputs:
attachInterrupt(INT_PIN1, getEncoderTickNumber, RISING);
attachInterrupt(INT_PIN2, getEncoderTickNumber, RISING);
attachInterrupt(INT_PIN3, getEncoderTickNumber, RISING);
attachInterrupt(INT_PIN4, getEncoderTickNumber, RISING);
The function getEncoderTickNumber() cannot be the interrupt handler because it blocks with a while(1) loop - it will quickly trigger the watchdog and reboot. Additionally, you've already used this function as a task which runs in the background (and seems to expect input from the interrupt handlers).
Finally, you seem have a more suitable candidate for the position of an interrupt handler - the function io_expander_interrupt() - which currently doesn't do anything useful. Let's fix that.
You would need 4 interrupt handlers, one per each GPIO you're monitoring. Each handler is attached to its respective GPIO pin, triggers when the IO rises and each does its own encoder calculation. A simple implementation without extra tasks would look like this:
#include <Arduino.h>
// Motor encoder output pulse per rotation (AndyMark Neverest 60)
int ENC_COUNT_REV = 420;
// Pulse count from encoder. Must be volatile as it's shared between ISR and main task
volatile int encoderValueA1 = 0;
volatile int encoderValueA2 = 0;
volatile int encoderValueA3 = 0;
volatile int encoderValueA4 = 0;
#define INT_PIN1 17
#define INT_PIN2 18
#define INT_PIN3 19
#define INT_PIN4 16
void isr_rising_gpio1() {
encoderValueA1++
}
void isr_rising_gpio2() {
encoderValueA2++
}
void isr_rising_gpio3() {
encoderValueA3++
}
void isr_rising_gpio4() {
encoderValueA4++
}
void setup()
{
Serial.begin(115200);
pinMode(INT_PIN1, INPUT);
attachInterrupt(INT_PIN1, isr_rising_gpio1, RISING);
pinMode(INT_PIN2, INPUT);
attachInterrupt(INT_PIN2, isr_rising_gpio2, RISING);
pinMode(INT_PIN3, INPUT);
attachInterrupt(INT_PIN3, isr_rising_gpio3, RISING);
pinMode(INT_PIN4, INPUT);
attachInterrupt(INT_PIN4, isr_rising_gpio4, RISING);
}
void loop()
{
int rpm1 = (encoderValueA1 * 60) / ENC_COUNT_REV;
encoderValueA1 = 0;
int rpm2 = (encoderValueA2 * 60) / ENC_COUNT_REV;
encoderValueA2 = 0;
int rpm3 = (encoderValueA3 * 60) / ENC_COUNT_REV;
encoderValueA3 = 0;
int rpm4 = (encoderValueA4 * 60) / ENC_COUNT_REV;
encoderValueA4 = 0;
Serial.print("1:");
Serial.print(rpm1);
Serial.print(" 2:");
Serial.print(rpm2);
Serial.print(" 3:");
Serial.print(rpm3);
Serial.print(" 4:");
Serial.println(rpm4);
vTaskDelay(pdMS_TO_TICKS(1000));
}

Rotary encoder strange behaviour

I have problem with results (on serial monitor) of rotary encoder.
I am using Arduino UNO and RotaryEncoder library.
When I am running example code serial monitor show proper values when rotating with any speed.
I want to use encoder to change volume in Df-player.
Problem starts when I want to use this code together with more complicated one - Mp3 player.
It actually works only when I am rotating encoder very very slowly
#include <SPI.h>
#include <MFRC522.h>
#include <Arduino.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
#include <RotaryEncoder.h>
#define RST_PIN 9 // Configurable, see typical pin layout above
#define SS_PIN 10 // Configurable, see typical pin layout above
#define PIN_IN1 2
#define PIN_IN2 3
#define ROTARYSTEPS 1
#define ROTARYMIN 0
#define ROTARYMAX 30
const int playPauseButton = 4;
const int shuffleButton = 5;
boolean isPlaying = false;
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
SoftwareSerial mySoftwareSerial(5, 6); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);
// Setup a RotaryEncoder with 2 steps per latch for the 2 signal input pins:
RotaryEncoder encoder(PIN_IN1, PIN_IN2, RotaryEncoder::LatchMode::TWO03);
// Last known rotary position.
int lastPos = -1;
//*****************************************************************************************//
void setup() {
Serial.begin(9600); // Initialize serial communications with the PC, COMMENT OUT IF IT FAILS TO PLAY WHEN DISCONNECTED FROM PC
mySoftwareSerial.begin(9600);
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
while (! Serial);
encoder.setPosition(5 / ROTARYSTEPS); // start with the value of 5.
pinMode(playPauseButton, INPUT_PULLUP);
pinMode(shuffleButton, INPUT_PULLUP);
Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
if (!myDFPlayer.begin(mySoftwareSerial)) { //Use softwareSerial to communicate with mp3.
Serial.println(F("Unable to begin:"));
Serial.println(F("1.Please recheck the connection!"));
Serial.println(F("2.Please insert the SD card!"));
}
Serial.println(F("DFPlayer Mini online. Place card on reader to play a spesific song"));
//myDFPlayer.volume(15); //Set volume value. From 0 to 30
//volumeLevel = map(analogRead(volumePot), 0, 1023, 0, 30); //scale the pot value and volume level
myDFPlayer.volume(5);
//prevVolume = volumeLevel;
//----Set different EQ----
myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
// myDFPlayer.EQ(DFPLAYER_EQ_POP);
// myDFPlayer.EQ(DFPLAYER_EQ_ROCK);
// myDFPlayer.EQ(DFPLAYER_EQ_JAZZ);
// myDFPlayer.EQ(DFPLAYER_EQ_CLASSIC);
// myDFPlayer.EQ(DFPLAYER_EQ_BASS);
}
//*****************************************************************************************//
void loop() {
encoder.tick();
// get the current physical position and calc the logical position
int newPos = encoder.getPosition() * ROTARYSTEPS;
if (newPos < ROTARYMIN) {
encoder.setPosition(ROTARYMIN / ROTARYSTEPS);
newPos = ROTARYMIN;
} else if (newPos > ROTARYMAX) {
encoder.setPosition(ROTARYMAX / ROTARYSTEPS);
newPos = ROTARYMAX;
} // if
if (lastPos != newPos) {
Serial.println(newPos);
myDFPlayer.volume(newPos);
lastPos = newPos;
} // if
// Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
MFRC522::MIFARE_Key key;
for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;
//some variables we need
byte block;
byte len;
MFRC522::StatusCode status;
if (digitalRead(playPauseButton) == LOW) {
if (isPlaying) {
myDFPlayer.pause();
isPlaying = false;
Serial.println("Paused..");
}
else {
isPlaying = true;
myDFPlayer.start();
Serial.println("Playing..");
}
delay(500);
}
if (digitalRead(shuffleButton) == LOW) {
myDFPlayer.randomAll();
Serial.println("Shuffle Play");
isPlaying = true;
delay(1000);
}
//-------------------------------------------
// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
if ( mfrc522.PICC_IsNewCardPresent()) {
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}
Serial.println(F("**Card Detected:**"));
//-------------------------------------------
mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid)); //dump some details about the card
//mfrc522.PICC_DumpToSerial(&(mfrc522.uid)); //uncomment this to see all blocks in hex
//-------------------------------------------
Serial.print(F("Number: "));
//---------------------------------------- GET NUMBER AND PLAY THE SONG
byte buffer2[18];
block = 1;
len = 18;
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 1, &key, &(mfrc522.uid)); //line 834
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Authentication failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
status = mfrc522.MIFARE_Read(block, buffer2, &len);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Reading failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
//PRINT NUMBER
String number = "";
for (uint8_t i = 0; i < 16; i++)
{
number += (char)buffer2[i];
}
number.trim();
Serial.print(number);
//PLAY SONG
myDFPlayer.play(number.toInt());
isPlaying = true;
//----------------------------------------
Serial.println(F("\n**End Reading**\n"));
delay(1000); //change value if you want to read cards faster
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
}
}
Any ideas what is wrong?
You have a delay(1000) in your main loop, and since your RotaryEncoder object seems to need a tick() function, i am assuming that it is not interrupt driven. This means that it will check only once per second if it has moved to the next step.
If a rotary encoder is stepped twice, and the middle step is missed by the MCU, the latter has no way of knowing which way round the encoder has turned.
So in this case you can only turn it one step per second.
What you need is, either:
a free running main loop, which goes round at least 100 times per second. (less nice)
a rotary encoder driver that is interrupt driven. (very nice)
I don't know if such a library exists, because i tend not to use arduino libs, but it is a very good exercise to write your own using GPIO interrupts.

Reading multiple sensors with different datatypes

I'm trying to read multiple sensors and saving all that data in one, singular, *.txt file. This is needed to enable it to analize and easily fill a database. But here is the catch, not all the sensors give int values, and as I learned the hard way, "String" gives to much unpredictable errors.
I want to read:
Temperature
Humidity
Light intensity
Sound
all saved as int
I also want to save
2 Accelero values (x,yand z values) as Float;
a piece of text, just to log a status or debug as a String.
I tried to fill them into array but I'm overlooking something. Can someone please point me in the correct direction to make it work, that would help me alot!
For your interest, it should become a datalogger for a trailer for horses. So I get feedback about forces while driving and also the climate of the trailer and trigger camera and sound to monitor the animals (will be next step to livestream it and make it a IOT-system).
The code:
#include <SPI.h>
//SDcard
#include <SD.h>
Sd2Card card;
SdVolume volume;
SdFile root;
const int chipSelect = 10;
File DataFile;
// Multiplexer 16 kanalen CD74HC4067
int pinS0 = 4;
int pinS1 = 5;
int pinS2 = 6;
int pinS3 = 7;
int pinSIG = A0;
//RTC
#include "RTClib.h"
RTC_DS1307 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
//Acelerometer
int RawMin = 0; // initialize minimum and maximum Raw Ranges for each axis
int RawMax = 1023;
//DHT1&2
#include <DHT.h>
#define DHTPIN2 8
#define DHTTYPE2 DHT11 // DHT 11 or DHT22
DHT dht2(DHTPIN2, DHTTYPE2);
#define DHTPIN1 13
#define DHTTYPE1 DHT11 // DHT 11 or DHT22
DHT dht1(DHTPIN1, DHTTYPE1);
// uint32_t delayMS;
int Temp2 = 0;
int Hum2 = 0;
int Temp1 = 0;
int Hum1 = 0;
//LDR
int LDRValue = 0;
//Sound
int SoundValue=0;
//Camera
unsigned long StartMillis; //some global variables available anywhere in the program
unsigned long CurrentMillis;
const unsigned long Period = 10000; //the value is a number of milliseconds
byte Parameter = 0; //parameter for using multiple timer to have start and stop statement camer
int Trigger = 9;
String FilmStatus;
//PIR
int PIRValue = 0; // variable for reading the pin status
//Header print
int Hoofding = 1; //NOG TE Doen!! (if lus om header ook te printen op SD
//String declaration
String AccelString1,AccelString2, Header;
//int Data[10];
// String DataString,AccelString2, AccellString1, DHTString, FilmStatus;
void setup() {
//Start Serial monitor --> needs to be disabled to work on battery
Serial.begin(9600);
while (!Serial) { // wait for serial port to connect. Needed for native USB port only ( against usb inconsistency)
;
}
//Multiplexer
pinMode(pinS0, OUTPUT);
pinMode(pinS1, OUTPUT);
pinMode(pinS2, OUTPUT);
pinMode(pinS3, OUTPUT);
//Start SD + basic check up + make file/ read file
QcheckSD();
DataFile = SD.open("DataFile.txt", FILE_WRITE);
// if the file opened, write to it:
if (DataFile) {
Serial.println("Writing to DataFile.txt possible.");
DataFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening DataFile.txt");
}
//start RTC
checkRTC();
//Check time RTC
checkTime();
//DHT start
dht2.begin();
dht1.begin();
//Camera start background
pinMode(Trigger, OUTPUT);
digitalWrite(Trigger, LOW);
delay (1000);
StartMillis = millis(); //initial start time
//Stings
AccelString1= String();
AccelString2= String();
FilmStatus= String();
//HEADER
String Header=String("X1;Y1;Z1;X2;Y2;Z2;T1;H1;T2;H2;LDR;Sound;PIR;Millis;FilmStatus");
Serial.println(Header);
}
void loop() {
//RTC
DateTime now = rtc.now();
//Acelerometer 1&2
//Read raw values
int xRaw2 = MUX(9);
int yRaw2 = MUX(10);
int zRaw2 = MUX(11);
// Convert raw values to 'milli-Gs"
long xScaled2 = map(xRaw2, RawMin, RawMax, -3000, 3000);
long yScaled2 = map(yRaw2, RawMin, RawMax, -3000, 3000);
long zScaled2 = map(zRaw2, RawMin, RawMax, -3000, 3000);
// re-scale to fractional Gs
float xAccel2 = xScaled2 / 1000.0; //used to be float
float yAccel2 = yScaled2 / 1000.0;
float zAccel2 = zScaled2 / 1000.0;
AccelString2 = String(xAccel2+';'+ yAccel2+';'+ zAccel2);
//Read raw values
int xRaw1 = MUX(1);
int yRaw1 = MUX(2);
int zRaw1 = MUX(3);
// Convert raw values to 'milli-Gs"
long xScaled1 = map(xRaw1, RawMin, RawMax, -3000, 3000);
long yScaled1 = map(yRaw1, RawMin, RawMax, -3000, 3000);
long zScaled1 = map(zRaw1, RawMin, RawMax, -3000, 3000);
// re-scale to fractional Gs
float xAccel1 = xScaled1 / 1000.0;
float yAccel1 = yScaled1 / 1000.0;
float zAccel1 = zScaled1 / 1000.0;
String AccelString1 =String( xAccel1+';'+ yAccel1+';'+zAccel1);
//DHT1&2
Temp2= dht2.readTemperature();
Hum2= dht2.readHumidity();
Temp1= dht1.readTemperature();
Hum1= dht1.readHumidity();
//LDR reading
LDRValue = analogRead (A3); //analog read van arduino omdat ander interferentie met mic!!!
//Sound
SoundValue= MUX(3);
//Camera
CurrentMillis = millis();
if (Parameter==0)
{
digitalWrite(Trigger, HIGH);
delay(50);
digitalWrite(Trigger, LOW);
FilmStatus= String("StartTrigger");
Parameter=1;
}
if (CurrentMillis-StartMillis>=Period && Parameter==1)
{
digitalWrite(Trigger, HIGH);
FilmStatus= String("EndTrigger");
delay(50);
digitalWrite(Trigger, LOW);
StartMillis=CurrentMillis;
Parameter=0;
}
//PIR
PIRValue = MUX(6);
//Fill array
int Data[8]={Temp1,Hum1,Temp2,Hum2,SoundValue,PIRValue,LDRValue,CurrentMillis};
float FloatData[6]={xAccel1,yAccel1,zAccel1,xAccel2,yAccel2,zAccel2};
String StringData[1]={FilmStatus};
//File open en save to SD
DataFile = SD.open("DataFile.txt", FILE_WRITE);
for (byte i = 0; i <8 ; i = i + 1) {
DataFile.print(Data[i]);
DataFile.print(";");
Serial.print(Data[i]);
Serial.print(";");
}
for (byte i = 0; i <6 ; i = i + 1) {
DataFile.print(FloatData[i]);
DataFile.print(";");
Serial.print(FloatData[i]);
Serial.print(";");
}
DataFile.print(StringData[1]);
Serial.print(StringData[1]);
DataFile.println("EOF");
Serial.println("EOF");
DataFile.close();
//delay (500);
}
void QcheckSD()
{
Serial.print("Initializing SD card...");
if (!SD.begin(10)) {
Serial.println("initialization failed!");
while (1);
}
Serial.println("initialization done.");
}
void checkRTC()
{
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
} else{
Serial.println( "found RTC");
}
if (! rtc.isrunning()) {
Serial.println("RTC is NOT running, let's set the time!");
// When time needs to be set on a new device, or after a power loss, the
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
}
// When time needs to be re-set on a previously configured device, the
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
}
void checkTime()
{
DateTime now = rtc.now();
Serial.print(now.day(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.year(), DEC);
Serial.print(" (");
Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
Serial.print(") ");
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
}
int MUX(int channel){
// Define connection with arduino
int MUXpin[] = {pinS0, pinS1, pinS2, pinS3};
// Table of all combinations of pins
int channely[16][4]={
{0,0,0,0},{1,0,0,0},{0,1,0,0},{1,1,0,0},{1,0,1,0},{0,1,1,0},{1,1,1,0},
{0,0,0,1},{1,0,0,1},{0,1,0,1},{1,1,0,1},{0,0,1,1},{1,0,1,1},{0,1,1,1},{1,1,1,1} // Kanaal 1-15
};
//Configuration of te control pin with a for loop
for(int i = 0; i < 4; i ++){
digitalWrite(MUXpin[i], channely[channel][i]);
}
// Reading of analogvalue of SIGpin
int ValueSIG = analogRead(pinSIG);
return ValueSIG;
}
Really appreciate your time, I know there is still some "junk" in the code from previous attempts to get it working. All suggestions are welcome, I'm eager to improve!
PS; if you need any hardwork specs let me know!
Define a structure for the statistics you are trying to capture:
struct Stats {
int temperature;
int humidity;
int lightIntensity;
int sound;
float accel; // This needs to be 6 floats I think?
std::string text;
}
When you start reading data, instantiate one of these and populate it:
Stats s; // create
s.temperature = Mux(9); // Or however you read the values...
s.humidity = Mux(10);
Then create a function for printing a Stats object:
void printStats(const Stats& s) {
// ... setup DataFile
// Print values into file...
DataFile.print(s.temperature);
DataFile.print(";");
DataFile.print(s.humidity);
/// ... and so on
}

Atmega328P+ENC28J60 freezes after 12 hours operation

I am quite new to the ethernet world. So please bear with me if I do ask stupid questions.
I designed a PCB using Atmega328P+ENC28J60 chip (schematic attached in the images below - sch1, sch2). The function of this board is basically sending GET requests to the server and retrieve a set of json data to turn on output pins, so based on my understanding my board acts as a client only right? The code is attached below:
#include <EEPROM.h>
#include <ArduinoJson.h>
#include <EthernetENC.h>
#define OUT0 2
#define OUT1 A3
#define OUT2 A2
#define OUT3 A1
#define OUT4 A0
#define OUT5 9
#define OUT6 8
#define OUT7 7
#define OUT8 6
#define OUT9 5
#define CS 10
// mac: 46 57 5a 6b 48 51
#define HOSTNAME "autolighting.afa-sports.com"
#define ID_SIZE 6
static byte mac[ID_SIZE];
static char macBuffer[ID_SIZE*2+1];
const byte output[] PROGMEM = {OUT0, OUT1, OUT2, OUT3, OUT4, OUT5, OUT6, OUT7, OUT8, OUT9};
EthernetClient client;
void clientRead() {
StaticJsonDocument<40> filter;
StaticJsonDocument<120> doc;
filter.clear();
doc.clear();
filter["data"]["relay_actions"] = true;
client.find("\r\n\r\n");
deserializeJson(doc, client, DeserializationOption::Filter(filter));
client.flush();
delay(50);
if (!doc["data"]["relay_actions"].isNull()) {
for (byte i = 0; i < 10; i++) {
// Serial.print(doc["data"]["relay_actions"][i].as<bool>());
digitalWrite(pgm_read_byte_near(&output[i]), doc["data"]["relay_actions"][i].as<bool>());
}
// Serial.println();
}
filter.clear();
doc.clear();
}
void sendReq() {
client.println(F("GET /api/iot/master-controller/get-command HTTP/1.1"));
client.println(F("Host: autolighting.afa-sports.com"));
// client.println(F("DEVICE-ID: 46575a6b4851"));
client.print(F("DEVICE-ID: "));
client.println(macBuffer);
client.println(F("Connection: close"));
client.println();
}
void setup() {
Serial.begin(115200);
for (byte i = 0; i < 10; i++) {
pinMode(pgm_read_byte_near(&output[i]), OUTPUT);
digitalWrite(pgm_read_byte_near(&output[i]), LOW);
}
for (uint8_t i = 0; i < ID_SIZE; i++) {
byte charByte = EEPROM.read(i);
if (charByte != 0) {
char temp[2];
mac[i] = charByte;
itoa(mac[i], temp, 16);
strcat(macBuffer, strlwr(temp)); // REMOVE strlwr IN RELEASE VERSION
free(temp);
delay(10);
}
}
strcat(macBuffer, '\0');
Ethernet.init(CS);
while (!Ethernet.begin(mac));
client.setTimeout(5000);
delay(1000);
}
void loop() {
while (!Ethernet.begin(mac)); // init fail
delay(1000);
if (client.connect(HOSTNAME, 80)) {
sendReq();
clientRead();
client.stop();
}
delay(3000);
}
Due to the high SRAM consumption and I might have other things (not sure what yet) to add in to the board in the future, I tried to minimize the dynamic memory by changing this (in the uipethernet-conf.h file):
#define UIP_SOCKET_NUMPACKETS 5
#define UIP_CONF_MAX_CONNECTIONS 4
#define UIP_CONF_UDP_CONNS 4
to this:
#define UIP_SOCKET_NUMPACKETS 2
#define UIP_CONF_MAX_CONNECTIONS 2
#define UIP_CONF_UDP_CONNS 1
I'm wondering will this affect the system performance? Btw, I've also set the timeout to 5s
After 13 hours of smooth operation, the board freezes and only became normal when i hard-reset the board. Currently, I'm connecting my board to a wireless extender, because I am not sitting right next to the wifi router. It looks like a memory leakage issue to me, but does memory leakage issue still exists in the latest ArduinoJson and EthernetENC/UIPEthernet library?
P/S: I was using UIPEthernet.h previously, but someone guided me to try out the EthernetENC library, the memory consumption definitely gone down a little bit, but the freezing problem still persist
Feel free to point out any mistakes I make, still in the learning adventure. =)
Your help is greatly appreciated. Thank you very much.
Library version:
ArduinoJson 6.17.2
EthernetENC 2.0.0
UIPEthernet 2.0.9
Schematics:
don't have these hardware, only analyses based on your code and Arduino references.
from your code
while (!Ethernet.begin(mac)); // init fail
which "may" cause freeze if :
Ethernet.begin always return false
is Ethernet.begin "ok" to call multiple time ?
These are some reference which may help :
Arduino DHCP failed to configure
https://electronics.stackexchange.com/questions/67045/ethernet-begin-only-works-with-sd-card-removed-why
according to the wiki :
https://github.com/jandrassy/EthernetENC/wiki/Examples
You should use :
Ethernet.maintain();
client.available();
write your own delay function :
void mDelay(unsigned long milliseconds) {
const unsigned d = 1;
while (milliseconds > d) {
Ethernet.maintain();
delay(d);
milliseconds -= d;
}
Ethernet.maintain();
delay(milliseconds);
}
note: for arduino or electronics question, may be
https://electronics.stackexchange.com/
is a more suitable site.
not sure about if the hardware can handle, you may try to "burst test" :
void loop() {
unsigned long currentMillis = millis();
Serial.print("Time: ");
Serial.println(currentMillis);
// burst test
if (client.connect(HOSTNAME, 80)) {
sendReq();
Serial.print(", After sendReq(); ");
clientRead();
Serial.print(", After client.clientRead(); ");
client.stop();
Serial.print(", After client.stop(); ");
}
mdelay( 500 );
Serial.println( ', mdelay(500); ' );
// mdelay will call Ethernet.maintain();
// Serial.print("After Ethernet.maintain(); ");
// use Serial.println to check where it freeze ?
}
based on your code, may be these can help to reduce memory problem :
move these two outside of void clientRead() as these 2 used every 4 seconds :
4 sec * 60 = 240 times / minutes
240 * 24 = 5760 times / day
StaticJsonDocument<40> filter;
StaticJsonDocument<120> doc;
void clientRead() {
...
note: all the code are illustration, not tested. you may need to modify to make it work.
note: please check with your hardware if it can handle, or will it burn when run such test ?
lots of thanks to #ocrdu and #Flash Ang for the suggestions, the code below is the working code and my PCB has been running continuously for 58 hours till now:
#include <EEPROM.h>
#include <ArduinoJson.h>
//#include <UIPEthernet.h>
#include <EthernetENC.h>
#define OUT0 2
#define OUT1 A3
#define OUT2 A2
#define OUT3 A1
#define OUT4 A0
#define OUT5 9
#define OUT6 8
#define OUT7 7
#define OUT8 6
#define OUT9 5
#define CS 10
// host name: "autolighting.afa-sports.com
// resource: "/api/iot/master-controller/get-command"
// mac: 46 57 5a 6b 48 51
// mac (char): FWZkHQ
#define HOSTNAME "autolighting.afa-sports.com"
#define ID_SIZE 6
static byte mac[ID_SIZE];
static char macBuffer[ID_SIZE*2+1];
const byte output[] PROGMEM = {OUT0, OUT1, OUT2, OUT3, OUT4, OUT5, OUT6, OUT7, OUT8, OUT9};
EthernetClient client;
void clientRead() {
StaticJsonDocument<40> filter;
StaticJsonDocument<120> doc;
filter.clear();
doc.clear();
filter["data"]["relay_actions"] = true;
client.find("\r\n\r\n");
deserializeJson(doc, client, DeserializationOption::Filter(filter));
client.flush();
delay(50);
if (!doc["data"]["relay_actions"].isNull()) {
for (byte i = 0; i < 10; i++) {
// Serial.print(doc["data"]["relay_actions"][i].as<bool>());
digitalWrite(pgm_read_byte_near(&output[i]), doc["data"]["relay_actions"][i].as<bool>());
}
// Serial.println();
}
filter.clear();
doc.clear();
}
void sendReq() {
client.println(F("GET /api/iot/master-controller/get-command HTTP/1.1"));
client.println(F("Host: autolighting.afa-sports.com"));
// client.println(F("DEVICE-ID: 46575a6b4851"));
client.print(F("DEVICE-ID: "));
client.println(macBuffer);
client.println(F("Connection: close"));
client.println();
}
void setup() {
for (byte i = 0; i < 10; i++) {
pinMode(pgm_read_byte_near(&output[i]), OUTPUT);
digitalWrite(pgm_read_byte_near(&output[i]), LOW);
}
for (uint8_t i = 0; i < ID_SIZE; i++) {
byte charByte = EEPROM.read(i);
if (charByte != 0) {
char temp[2];
mac[i] = charByte;
itoa(mac[i], temp, 16);
strcat(macBuffer, strlwr(temp)); // REMOVE strlwr IN RELEASE VERSION
free(temp);
delay(10);
}
}
strcat(macBuffer, '\0');
Ethernet.init(CS);
while (!Ethernet.begin(mac));
client.setTimeout(5000);
delay(1000);
}
void loop() {
Ethernet.maintain();
while (!Ethernet.begin(mac)) //Serial.println(F("IF")); // init fail
// Serial.println(F("IS")); // init success
delay(1000);
if (client.connect(HOSTNAME, 80)) {
sendReq();
clientRead();
client.stop();
}
Ethernet.maintain();
delay(3000);
}
//int freeRam () { // check remaining RAM space
// extern int __heap_start, *__brkval;
// int v;
// return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
//}
This time to work smart, I used the default ip address to my router and monitor whether my PCB is still connected to the router by looking at the DHCP client list, and remove all the serial commands in the code. I'm afraid for my past experiences on the disconnection issues, it might be just a short temporary disconnect from the router, instead of a permanent disconnection.
I'm sorry if there is any lack of testing in this program. Thank you for the time spent to provide me all the useful suggestions =)

Overcome Arduino memory limitations with multiple sensors

I have an Arduino Nano piggybacked on a ENC28j60 ethernet module. I have eight (8) DHT22 sensors (named A, B, C ... H ) and i want to write their temperature and humidity data to Pushingbox.
The program is working great with ONE sensor. So that's good. However when i un-remark (i.e. take out the //'s) for anything more than one sensor, yes even for ONE other sensor, it won't write anything at all.
The arduino IDE complier says:
Sketch uses 23824 bytes (77%) of program storage space. Maximum is 30720 bytes.
Global variables use 1870 bytes (91%) of dynamic memory, leaving 178 bytes for local variables. Maximum is 2048 bytes.
Low memory available, stability problems may occur.
FYI, If i un-remark just one other sensor it goes up +2% to 93% of dynamic memory and stops working. So i'm assuming its a memory problem. i have already removed all floats (and made integers *10 to keep one decimal place of accuracy), i need 8 instances of DHT so considered reducing the library size but the .h seems tiny and pretty lean already (within the .h file it even boasts: Very low memory footprint - Very small code. so i havent modified this or the .cpp.
The overall code i have written is not large, maybe there are some in-efficiencies there, but i can't see that it is going to make anything near the amount of memory saving needed for the next 7 sensors.
The full arduino code (written for all 8 sensors, with 'ghosted' bits for 4 sensors and in use only working for one sensor) is below:
#include "DHTesp.h"
//#include <SPI.h>
#include <UIPEthernet.h>
DHTesp dhtA;
//DHTesp dhtB;
//DHTesp dhtC;
//DHTesp dhtD;
//DHTesp dhtE;
//DHTesp dhtF;
//DHTesp dhtG;
//DHTesp dhtH;
const int ledPin = LED_BUILTIN;
int ledState = LOW;
int interval = 10; // this is the number of seconds between reads (120=2mins)
int numReads = 5; // Number of reads between posting to google docs.
int multFact = 10; // multiplication factor 10 = 1 dec. place 100 = 2 dec places
byte mac[] = {0xBE, 0xEF, 0xDE, 0xAD, 0xDE, 0xAD }; //Ethernet shield MAC. Andy's working {0xBE, 0xEF, 0xDE, 0xAD, 0xDE, 0xAD}
byte ip[] = { 192,168,1,12 }; // Arduino device IP address
char devid [] = "vCE3D036xxxxxxxx"; // Gsheets device ID from Pushingbox ('x's for privacy:)
char server[] = "api.pushingbox.com";
EthernetClient client;
void setup()
{
Serial.begin(9600);
Serial.println ("RESTART");
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Trying to connect...");
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore:
while(true);
}
else{
Serial.print("OK, connected. Ethernet ready. ");
// print the Ethernet board/shield's IP address:
Serial.print("IP address: ");
Serial.println(Ethernet.localIP());
}
// give the Ethernet shield a second to initialize:
delay(1000);
Serial.println();
//Serial.println("A-Stat\t\tA-Temp (C)\tA-humdid%\tA-HeatI (C)\tB-Stat\t\tB-Temp (C)\tA-humdid%\tB-HeatI (C)");
Serial.println("\t\t\t\tt-A\th-A\tt-B\th-B\tt-C\th-C\tt-D\th-D\tt-E\th-E\tt-F\th-F\tt-G\th-G\tt-H\th-H");
//hey dB for some reason the Ethernet sheild uses pin D2 :( and pins 10,11,12,13
// https://arduinodiy.wordpress.com/2013/04/07/connect-an-enc28j60-ethernet-module-to-an-arduino/
// assign data pins
dhtA.setup(3);
//dhtB.setup(4);
//dhtC.setup(5);
//dhtD.setup(6);
//dhtE.setup(7);
//dhtF.setup(8);
//dhtG.setup(9);
//dhtH.setup(10); //watchout! i think Ethernet uses this pin too?
pinMode(ledPin, OUTPUT);
//end of void setup
}
void loop()
{
int Ahumid = 0; int Atemp = 0;
int Bhumid = 0; int Btemp = 0;
int Chumid = 0; int Ctemp = 0;
int Dhumid = 0; int Dtemp = 0;
//int Ehumid = 0; int Etemp = 0;
//int Fhumid = 0; int Ftemp = 0;
//int Ghumid = 0; int Gtemp = 0;
//int Hhumid = 0; int Htemp = 0;
int j=0;
for (j = 1; j <= numReads ; j++ ) {
int p = 0;
for (p=1; p <= interval ; p++) {
delay (1000);
// swap the led state
if (ledState == LOW) { ledState = HIGH; } else { ledState = LOW; }
Serial.print (p); //show the seconds passing
Serial.print (",");
digitalWrite(ledPin, ledState);
}
Serial.print (" Reading");
Atemp += dhtA.getTemperature()*multFact; Ahumid += dhtA.getHumidity()*multFact;
//Btemp += dhtB.getTemperature()*multFact; Bhumid += dhtB.getHumidity()*multFact;
//Ctemp += dhtC.getTemperature()*multFact; Chumid += dhtC.getHumidity()*multFact;
//Dtemp += dhtD.getTemperature()*multFact; Dhumid += dhtD.getHumidity()*multFact;
// print the readings
//Serial.print(dhtA.getStatusString());
Serial.print("\t"); Serial.print(Atemp);
Serial.print("\t"); Serial.print(Ahumid);
Serial.print("\t"); Serial.print(Btemp);
Serial.print("\t"); Serial.print(Bhumid);
Serial.print("\t"); Serial.print(Ctemp);
Serial.print("\t"); Serial.print(Chumid);
Serial.print("\t"); Serial.print(Dtemp);
Serial.print("\t"); Serial.print(Dhumid);
Serial.println();
// and so here endeth 'j', the number of reads
}
Serial.print ("Avg...");
Atemp = Atemp/numReads; Ahumid = Ahumid/numReads;
Btemp = Btemp/numReads; Bhumid = Bhumid/numReads;
Ctemp = Ctemp/numReads; Chumid = Chumid/numReads;
Dtemp = Dtemp/numReads; Dhumid = Dhumid/numReads;
// print the averages so we can see what it is going to send
Serial.print("\t\t\t");
Serial.print("\t"); Serial.print(Atemp); Serial.print("\t"); Serial.print(Ahumid);
Serial.print("\t"); Serial.print(Btemp); Serial.print("\t"); Serial.print(Bhumid);
Serial.print("\t"); Serial.print(Ctemp); Serial.print("\t"); Serial.print(Chumid);
Serial.print("\t"); Serial.print(Dtemp); Serial.print("\t"); Serial.print(Dhumid);
Serial.println();
Serial.print ("Prep for upload... ");
if (client.connect(server, 80))
{
Serial.print("Connected OK ... writing...");
client.print("GET /pushingbox?devid=");
client.print(devid);
client.print("&tempA="); client.print(Atemp);
client.print("&tempB="); client.print(Btemp);
client.print("&tempC="); client.print(Ctemp);
client.print("&tempD="); client.print(Dtemp);
client.print("&tempE=29&tempF=39&tempG=49&tempH=59");
//now humidity too
client.print("&humidA="); client.print(Ahumid);
client.print("&humidB="); client.print(Bhumid);
client.print("&humidC="); client.print(Chumid);
client.print("&humidD="); client.print(Dhumid);
client.print("&humidE=26&humidF=27&humidG=28&humidH=29");
client.print("&submit=Submit");
client.println(" HTTP/1.1");
client.println("Host: api.pushingbox.com");
client.println("Connection: close");
client.println();
Serial.println("written OK. & connection closed.");
Serial.println(); //Serial.println();
delay(1000); // maybe take this out to keep time stable?
client.stop();
}
else {
Serial.println("** NO CONNEX **"); Serial.println();
}
//here endeth void loop
}
Extra info (that i dont think is relevant, but maybe): IDE compiler also reports:
WARNING: library DHT_sensor_library_for_ESP32 claims to run on [esp32] architecture(s) and may be incompatible with your current board which runs on [avr] architecture(s).
Use the F macro for double-quoted string literal prints. Instead of this:
Serial.println ("RESTART");
or
client.print("GET /pushingbox?devid=");
... do this:
Serial.println ( F("RESTART") );
or
client.print( F("GET /pushingbox?devid=") );
This will easily save a bunch o' RAM.
I would also suggest using the single quoted literal for single characters, not the double quote:
Serial.print( '\t' );