I'm trying to merge some code from another Arduino project into my current project. What i'm try to do is post the readings that I get from my current project to a web server, so that I can access it from my laptop or mobile device.
When I try to merge server code, I get the error 'dustDensity' is not captured. Not really sure as to why this is happening, and would appreciate some help to get around this issue.
Trying to compile this code in Arduino IDE but it won't.
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <SPIFFS.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <SPIFFS.h>
#define USE_AVG
#define LED_BUILTIN 13
// Replace with your network credentials
const char* ssid = "ssid";
const char* password = "password";
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
// Arduino pin numbers.
const int sharpLEDPin = 18; // Arduino digital pin 7 connect to sensor LED.
const int sharpVoPin = 25; // Arduino analog pin 5 connect to sensor Vo.
// For averaging last N raw voltage readings.
#ifdef USE_AVG
#define N 100
static unsigned long VoRawTotal = 0;
static int VoRawCount = 0;
#endif // USE_AVG
// Set the typical output voltage in Volts when there is zero dust.
static float Voc = 0.6;
// Use the typical sensitivity in units of V per 100ug/m3.
const float K = 0.5;
/////////////////////////////////////////////////////////////////////////////
// Helper functions to print a data value to the serial monitor.
void printValue(String text, unsigned int value, bool isLast = false) {
Serial.print(text);
Serial.print("=");
Serial.print(value);
if (!isLast) {
Serial.print(", ");
}
}
void printFValue(String text, float value, String units, bool isLast = false) {
Serial.print(text);
Serial.print("=");
Serial.print(value);
Serial.print(units);
if (!isLast) {
Serial.print(", ");
}
}
/////////////////////////////////////////////////////////////////////////////
// Arduino setup function.
void setup() {
// Set LED pin for output.
pinMode(sharpLEDPin, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
// Start the hardware serial port for the serial monitor.
Serial.begin(9600);
// Wait two seconds for startup.
delay(2000);
Serial.println("");
Serial.println("GP2Y1014AU0F Demo");
Serial.println("=================");
}
// Arduino main loop.
void loop() {
// Turn on the dust sensor LED by setting digital pin LOW.
digitalWrite(sharpLEDPin, LOW);
// Wait 0.28ms before taking a reading of the output voltage as per spec.
delayMicroseconds(280);
// Record the output voltage. This operation takes around 100 microseconds.
int VoRaw = analogRead(sharpVoPin);
// Turn the dust sensor LED off by setting digital pin HIGH.
digitalWrite(sharpLEDPin, HIGH);
// Wait for remainder of the 10ms cycle = 10000 - 280 - 100 microseconds.
delayMicroseconds(9620);
// Print raw voltage value (number from 0 to 1023).
#ifdef PRINT_RAW_DATA
printValue("VoRaw", VoRaw, true);
Serial.println("");
#endif // PRINT_RAW_DATA
// Use averaging if needed.
float Vo = VoRaw;
#ifdef USE_AVG
VoRawTotal += VoRaw;
VoRawCount++;
if ( VoRawCount >= N ) {
Vo = 1.0 * VoRawTotal / N;
VoRawCount = 0;
VoRawTotal = 0;
} else {
return;
}
#endif // USE_AVG
// Compute the output voltage in Volts.
Vo = Vo / 1024.0 * 5.0;
printFValue("Vo", Vo*1000.0, "mV");
// Convert to Dust Density in units of ug/m3.
float dV = Vo - Voc;
if ( dV < 0 ) {
dV = 0;
Voc = Vo;
}
float dustDensity = dV / K * 100.0;
printFValue("DustDensity", dustDensity, "ug/m3", true);
Serial.println("");
if (dustDensity > 85.0) {
digitalWrite(LED_BUILTIN,HIGH);
}
else {
digitalWrite(LED_BUILTIN,LOW);
}
if(!SPIFFS.begin()){
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
// Print ESP32 Local IP Address
Serial.println(WiFi.localIP());
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/index.html");
});
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", dustDensity().c_str());
});
server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", VoRaw().c_str());
});
// Start server
server.begin();
} // END PROGRAM
So not sure, why it won't compile. I'm trying to send dustDensity to a website from my ESP32.
Your code is currently
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", dustDensity().c_str());
});
This code:
[](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", dustDensity().c_str());
}
is a "lambda expression". It's a function that won't be evaluated until request->send_P() is called. That means that dustDensity won't be defined at that point. For it to be available to the function it has to be "captured", which means that you must tell the lambda expression explicitly to make it available.
You'll also need to turn it into a C-string or String since the method wants a string argument.
So you need to rewrite this code to look more like this:
server.on("/temperature", HTTP_GET, [dustDensity](AsyncWebServerRequest *request){
request->send(200, "text/plain", String(dustDensity()));
});
The changes here are:
- add dustDensity to the brackets in the lambda so that it's captured and available inside the function
- change send_P to send because send_P is meant for sending strings stored in PROGMEM
- make a String from dustDensity so that send() has some text to send
ESPAsyncWebServer is extensively documented with lots of examples. I highly recommend reading the documentation if you're using it.
Related
I am trying to transmit data from an ultrasonic sensor to an LCD screen using two NRF24L01 modules connected to two separate Arduino UNOs for a distance sensor for a bike. As I am relatively new to Arduino and initially did not know how to use the NRF24L01 module, I followed a tutorial from https://www.electroniclinic.com/nrf24l01-multiple-transmitters-and-single-receiver-for-sensor-monitoring-using-arduino/
, implemented it into my code, and it is not working. I ensured on multiple occasions that the wiring for the NRF24L01 is correct for the Arduino UNOs and attempted to change radio channels, and no use. For others from the website it appeared to be working, but for me it is not. Both programs compile just fine. Is there an issue with my code or is it possible that my NRF24L01 is nonfunctional?
Here is my code:
Transmitter:
#include <RF24Network.h>
#include <RF24Network_config.h>
#include <Sync.h>
#include <RF24.h>
#include <SPI.h>
RF24 radio(5, 4); // radio module, pins 5,4 for (CE, CSN)
RF24Network network(radio);
const uint16_t this_node = 01; //address of arduino
const uint16_t node00 = 00;
//setting up pins for each device
const int buzzerPin = 10;
const int aheadTrigPin = 9;
const int aheadEchoPin = 8;
//initialize variables for ultrasonic sensor and data
unsigned long data[3];
unsigned long aheadDistance;
unsigned long aheadDuration;
void setup() {
Serial.begin(9600);
SPI.begin();
radio.begin();
network.begin(69, this_node);
radio.setDataRate(RF24_2MBPS);
pinMode(buzzerPin, OUTPUT);
pinMode(aheadTrigPin, OUTPUT);
pinMode(aheadEchoPin, INPUT);
}
void loop() {
//clears the "trig" condition for ultrasonic sensor
digitalWrite(aheadTrigPin, LOW);
delayMicroseconds(2);
//releases sound waves from ultrasonic sensor for 10 microseconds
digitalWrite(aheadTrigPin, HIGH);
delayMicroseconds(10);
digitalWrite(aheadTrigPin, LOW);
//reads "echo" pin to return sound wave travel time in microseconds
aheadDuration = pulseIn(aheadEchoPin, HIGH);
//calculating distance of ultrasonic sensor, in inches (distance = velocity * time)
aheadDistance = (aheadDuration * 0.034 / 2) * 2.54;
Serial.println(aheadDistance);
//activates buzzer to alert rider if danger values are met
if(aheadDistance <= 100) {
tone(buzzerPin, 255);
}
else {
noTone(buzzerPin);
}
//send data to main component
network.update();
data[0] = aheadDistance;
RF24NetworkHeader header(node00);
bool ok = network.write(header, &data, sizeof(data)); // send data
Serial.println("sent to NRF24 server");
delay(200);
}
The reason I am sending an array as the data is because I am currently working on having another transmitter to send data to a single receiver.
Receiver:
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <RF24Network.h>
#include <RF24Network_config.h>
#include <Sync.h>
#include <RF24.h>
#include <SPI.h>
//sets up timer for the LCD display to constantly run
//sets up OLED screen
LiquidCrystal_I2C display(0x27,20,4);
RF24 radio (10, 9); // CE, CSN, defines new RF24 radio
RF24Network network(radio);
const uint64_t this_node = 00;
//data variables that will be collected from other arduinos
unsigned long data[3];
unsigned long aheadDistance;
unsigned long groundDistance;
unsigned long backAheadDistance;
void setup()
{
Serial.begin(9600);
display.init(); // intialize lcd
display.backlight(); //open backlight of lcd
display.clear();
//initialize starting screen
display.setCursor(0, 0);
//set up radio module (reciever)
SPI.begin();
radio.begin();
network.begin(69, this_node);
radio.setDataRate(RF24_2MBPS);
}
//method to update screen with current data values
void displayDistance() {
display.setCursor(0, 0);
display.print("Bike Sensor");
display.setCursor(0, 1);
display.print("Front: ");
display.print(aheadDistance);
display.print(" in");
display.setCursor(0, 2);
display.print("Ground: ");
display.print(groundDistance);
display.print(" in");
display.setCursor(0, 3);
display.print("Back: ");
display.print(backAheadDistance);
display.print(" in");
display.display();
}
void connectionLost() // activates when main component is unable to connect to others
{
display.clear();
display.setCursor(0, 1);
display.print("Connection");
display.setCursor(0, 2);
display.print("Lost");
display.display();
}
void loop()
{
network.update();
while(network.available()) {
RF24NetworkHeader header;
Serial.println("connection found");
network.read(header, &data, sizeof(data));
Serial.println("data recieved");
if(header.from_node == 01) {
backAheadDistance = data[0];
}
if(header.from_node == 02) {
aheadDistance = data[1];
groundDistance = data[2];
}
displayDistance();
delay(100);
}
connectionLost();
Serial.println("no connection found");
delay(200);
}
//updates OLED screen and actually displays it on the module
It’s possible that your nRF24L01 is dead. I’ve had many. Some fail. I recommend those from EByte especially ML01DP5 and ML01SP4. These are good.
Also there’s a little known hardware issue: never let the FIFO buffers remain full for over 4ms. Of course it’s hard to know. So simply flush them often as a precaution. I have fixed my code this way and now it’s robust.
Good luck!
Malcolm
Firstly, I want to apologize as I am new to BLE connectivity and much of Arduino programming. I am busy with a project which in involved making a smart coffee scale which can output data to a smartphone via a BLE connection. I am working with an Arduino nano 33 IoT, and an hx711 load cell amplifier.
I need to create a program where I can send and receive data to and from the Arduino to the smartphone app. I have used standard ArduinoBLE peripheral libraries such as the "BatteryMonitor" sketch and the "ButtonLED" sketch. By combining both of these example sketches together I have managed to established a connection where I can send and receive data.
The problem arises when I try to use functions within the HX711 library such as scale.read(); to retrieve values being output from the hx711 amplifier. When I use a serial read function such as scale.read() the bluetooth connection fails before establishing itself properly. I imagine this is due to the scale.read() function interfering with the serial data being transmitted and received by the Arduino, but I have no clue how to get around this problem.
I basically want to change the battery monitor output to be the output of the value read from the hx711 load cell amplifier but I am struggling to get this to work.
#include "HX711.h"
#include <ArduinoBLE.h>
HX711 scale;
BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // BLE LED Service
// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEByteCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
BLEUnsignedCharCharacteristic batteryLevelChar("2A19", // standard 16-bit characteristic UUID
BLERead | BLENotify); // remote clients will be able to get notifications if this characteristic changes
int oldBatteryLevel = 0; // last battery level reading from analog input
long previousMillis = 0; // last time the battery level was checked, in ms
const int ledPin = LED_BUILTIN; // pin to use for the LED
double val;
void setup() {
Serial.begin(9600);
scale.begin(A1, A0); //Initialized scale on these pins
while (!Serial);
scale.set_scale(432.f); // this value is obtained by calibrating the scale with known weights; see the README for details
scale.tare(); // reset the scale to 0
// set LED pin to output mode
pinMode(ledPin, OUTPUT);
// begin initialization
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (1);
}
// set advertised local name and service UUID:
BLE.setLocalName("COFFEE");
BLE.setAdvertisedService(ledService);
// add the characteristic to the service
ledService.addCharacteristic(switchCharacteristic);
ledService.addCharacteristic(batteryLevelChar); // add the battery level characteristic
// add service
BLE.addService(ledService);
// set the initial value for the characeristic:
switchCharacteristic.writeValue(0);
// start advertising
BLE.advertise();
Serial.println("BLE LED Peripheral");
}
void loop()
{
// listen for BLE peripherals to connect:
BLEDevice central = BLE.central();
// if a central is connected to peripheral:
if (central) {
Serial.print("Connected to central: ");
// print the central's MAC address:
Serial.println(central.address());
// while the central is still connected to peripheral:
while (central.connected())
{
// Battery Monitor
// scale.read();
long currentMillis = millis();
// if 200ms have passed, check the battery level:
if (currentMillis - previousMillis >= 200) {
previousMillis = currentMillis;
// scale.read(); // This function alone will prevent the BLE connection from establishing properly.
updateBatteryLevel();
// outputScale();
}
// if the remote device wrote to the characteristic,
// use the value to control the LED:
if (switchCharacteristic.written()) {
if (switchCharacteristic.value()) { // any value other than 0
Serial.println("LED on");
digitalWrite(ledPin, HIGH); // will turn the LED on
} else { // a 0 value
Serial.println(F("LED off"));
digitalWrite(ledPin, LOW); // will turn the LED off
}
}
}
// when the central disconnects, print it out:
Serial.print(F("Disconnected from central: "));
Serial.println(central.address());
}
}
void updateBatteryLevel()
{
/* Read the current voltage level on the A0 analog input pin.
This is used here to simulate the charge level of a battery.
*/
int battery = analogRead(A0);
int batteryLevel = map(battery, 0, 1023, 0, 100);
if (batteryLevel != oldBatteryLevel) { // if the battery level has changed
// Serial.print("Battery Level % is now: "); // print it
Serial.println(batteryLevel);
batteryLevelChar.writeValue(batteryLevel); // and update the battery level characteristic
oldBatteryLevel = batteryLevel; // save the level for next comparison
}
}
void outputScale(){
int t, i, n, T;
double val, sum, sumsq, mean;
float stddev;
n = 20;
t = millis();
i = sum = sumsq = 0;
while (i<n) {
val = ((scale.read() - scale.get_offset()) / scale.get_scale());
sum += val;
sumsq += val * val;
i++;
}
t = millis() - t;
mean = sum / n;
stddev = sqrt(sumsq / n - mean * mean);
// Serial.print("Mean, Std Dev of "); Serial.print(i); Serial.print(" readings:\t");
Serial.print(sum / n, 3); Serial.print("\n"); // Serial.print(stddev, 3);
// Note: 2 sigma is 95% confidence, 3 sigma is 99.7%
//Serial.print("\nTime taken:\t"); Serial.print(float(t)/1000, 3); Serial.println("Secs\n");
/*
scale.power_down(); // put the ADC in sleep mode
delay(5000);
scale.power_up();
*/
}
You are initialising as scale.begin(A1, A0) while trying to read from the same A0 pin.
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.
Have some arduino code for temp loggers that is VERY NEARLY working....!
I've built an OTA routine so I can update them remotely, however the delay() loop I had to ensure it only logged temperatures every 15 mins is now causing problems as it effectively freezes the arduino by design for 15mins, meaning OTA wouldn't work whilst it is in this state.
Some suggestions say just to flip to millis() instead, but I can't seem to get this working and it's logging ~20 records every second at the moment.
Ideally I just want delay_counter counting up to the value in DELAY_TIME, then running the rest of the code and resetting the counter.
Can anyone help me and point out what I'm doing daft in my code???
// v2 Temp sensor
// Connecting to Home NAS
#include <DHT.h>
#include <DHT_U.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
#include <ESP8266mDNS.h>
#include <ArduinoOTA.h>
#include <InfluxDbClient.h>
#define SSID "xxx" //your network name
#define PASS "xxx" //your network password
#define VersionID "v3"
#define SensorName "ServerUnit" //name of sensor used for InfluxDB and Home Assistant
// Temp Sensor 1 - GardenTropical
// Temp Sensor 2 - GardenRoom
// Temp Sensor 3 - Greenhouse
// Temp Sensor 4 - OutsideGreenhouse
// Temp Sensor 5 - ServerUnit
// Connection Parameters for Jupiter InfluxDB
#define INFLUXDB_URL "http://192.168.1.5:8086"
#define INFLUXDB_DB_NAME "home_assistant"
#define INFLUXDB_USER "xxx"
#define INFLUXDB_PASSWORD "xxx"
// Single InfluxDB instance
InfluxDBClient client(INFLUXDB_URL, INFLUXDB_DB_NAME);
// Define data point with measurement name 'DaveTest`
Point sensor("BrynyneuaddSensors");
#define PORT 80
#define DHTPIN 4 // what pin the DHT sensor is connected to
#define DHTTYPE DHT22 // Change to DHT22 if that's what you have
#define BAUD_RATE 115200 //Another common value is 9600
#define DELAY_TIME 900000 //time in ms between posting data to Home Server
unsigned long delay_counter = 0;
DHT dht(DHTPIN, DHTTYPE);
//this runs once
void setup()
{
Serial.begin(BAUD_RATE);
// Connect to WIFI
WiFi.begin(SSID, PASS);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print("*");
}
// Initialise OTA Routine
ArduinoOTA.onStart([]() {
Serial.println("Start");
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.begin();
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
//initalize DHT sensor
dht.begin();
// set InfluxDB database connection parameters
client.setConnectionParamsV1(INFLUXDB_URL, INFLUXDB_DB_NAME, INFLUXDB_USER, INFLUXDB_PASSWORD);
// Add constant tags - only once
sensor.addTag("device", SensorName);
// Check server connection
if (client.validateConnection()) {
Serial.print("Connected to InfluxDB: ");
Serial.println(client.getServerUrl());
} else {
Serial.print("InfluxDB connection failed: ");
Serial.println(client.getLastErrorMessage());
Serial.println(client.getServerUrl());
Serial.println("Exiting DB Connection");
}
}
//this runs over and over
void loop() {
ArduinoOTA.handle();
float h = dht.readHumidity();
Serial.print("Humidity: ");
Serial.println(h);
// Read temperature as Fahrenheit (isFahrenheit = true)
float c = dht.readTemperature();
Serial.print("Temperature: ");
Serial.println(c);
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(c)) {
Serial.println("Reading DHT22 Failed, exiting");
return;
}
//update Influx DB channel with new values
updateTemp(c, h);
Serial.print("Writing to InfluxDB: ");
//INFLUXDB - clear temp data so it doesn't repeat
sensor.clearFields();
// Update Influx DB
sensor.addField("Temperature", c);
sensor.addField("Humidity", h);
Serial.println(sensor.toLineProtocol());
// Write data
client.writePoint(sensor);
//wait for delay time before attempting to post again
if(millis() >= DELAY_TIME){
delay_counter += 0;
}
//Increment Delay Counter
delay_counter++;
}
bool updateTemp(float tempC, float humid) {
WiFiClient client; // Create a WiFiClient to for TCP connection
Serial.println("Receiving HTTP response");
while (client.available()) {
char ch = static_cast<char>(client.read());
Serial.print(ch);
}
Serial.println();
Serial.println("Closing TCP connection");
client.stop();
return true;
}
Set a TimerObject. this seems to be what you want.
Download the Arduino TimerObject code from github and follow the installation instructions
#include "TimerObject.h"
Create the callback function
Create the TimerObject
Setup the TimerObject and periodically call update() in your loop():
// make sure to include the header
#include "TimerObject.h"
...
// setup your TimerObject
TimerObject* sensor_timer = new TimerObject(15 * 60 * 1000); // milliseconds
...
// define the stuff you want to do every 15 minutes and
// stick it in a function
// not sure what from your loop() needs to go in here
void doSensor()
{
float h = dht.readHumidity();
Serial.print("Humidity: ");
Serial.println(h);
// Read temperature as Fahrenheit (isFahrenheit = true)
float c = dht.readTemperature();
Serial.print("Temperature: ");
Serial.println(c);
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(c)) {
Serial.println("Reading DHT22 Failed, exiting");
return;
}
//update Influx DB channel with new values
updateTemp(c, h);
Serial.print("Writing to InfluxDB: ");
//INFLUXDB - clear temp data so it doesn't repeat
sensor.clearFields();
// Update Influx DB
sensor.addField("Temperature", c);
sensor.addField("Humidity", h);
Serial.println(sensor.toLineProtocol());
// Write data
client.writePoint(sensor);
}
...
// add the timer setup to your setup()
// probably at the end is a good place
void setup()
{
...
// lots of stuff above here
sensor_timer->setOnTimer(&doSensor);
sensor_timer->Start();
}
// modify your loop() to check the timer on every pass
void loop()
{
ArduinoOTA.handle();
sensor_timer->Update();
}
If you don't want to wait 15 minutes for the first call of doSensor, you can explicitly call it at the end of your setup() function before you start the timer.
Here is an simple example how to use millis()
int last_report = -777;//dummy value
int REPORT_INTERVAL = 15 *60 ; // 15 minutes
void loop() {
ArduinoOTA.handle();
int interval = millis() / 1000 - last_report;
if (interval < REPORT_INTERVAL) {
return;
}
last_report = millis() / 1000;
//do some important stuff
}
Make it simole and use easy code:
const unsigned long timeIntervall = 15*60*1000; // 15 minutes
unsigned long timeStamp = 0;
void setup(){....}
void loop() {
ArduinoOTA.handle(); // is running all the time
// Code in this section only runs every timeIntervall - rollover safe
if(millis() - timeStamp > timeIntervall ){
float h = dht.readHumidity();
......
// Write data
client.writePoint(sensor);
timeStamp = millis(); // reset the timer
}
}
I am having a problem with my code for arduino m0 (using microchip SAMD21). There are two SPI interfaces, first classic and second with int variable in front of the pin name, int MISO, for instance. Does someone know, how to control this classic SPI interface?
I have also attached my code.
PS: Code stucks in begin function of OZONE2CLICK sensor...
#include "Arduino.h"
#include <MQ131.h>
// include RFM69 library
#include <SPI.h>
// Local
#define PC_BAUDRATE 56700
#define MS_DELAY 0 // Number of milliseconds between data sending and LED signalization
#define LED_DELAY 100
#define Serial SerialUSB
// SD card
#define sd_cs_pin 35 // set SD's chip select pin (according to the circuit)
float PPMO2;
float PPBO2;
float MGM3O2;
float UGM3O2;
const byte pinSS = 2; //cs pin
const byte pinRDY = 12;
const byte pinSCK = 13;
const byte O2Pin = 10;
#define DcPin 8
// SD card file
File file; // SD library variable
// LEDS
#define D13_led_pin 42 // D13 LED
#define M_led_pin 36 // MLED
// Local variables
int idCounter = 1;
bool isBmeOk = true;
bool isSdOk = true;
bool isRadioOk = true;
bool isGpsConnected = true;
void OZONE2CLICKCalibrate ()
{
Serial.println("2");
//MQ131.begin(pinSS, pinRDY, O2Pin, LOW_CONCENTRATION, 10000); //(int _pinCS, int _pinRDY, int _pinPower, MQ131Model _model, int _RL)
Serial.println("99");
Serial.println("Calibration in progress...");
MQ131.calibrate();
Serial.println("Calibration done!");
Serial.print("R0 = ");
Serial.print(MQ131.getR0());
Serial.println(" Ohms");
Serial.print("Time to heat = ");
Serial.print(MQ131.getTimeToRead());
Serial.println(" s");
}
void OZONE2CLICKMeasure ()
{
Serial.println("Sampling...");
MQ131.sample();
Serial.print("Concentration O3 : ");
PPMO2 = MQ131.getO3(PPM);
Serial.print(PPMO2);
Serial.println(" ppm");
Serial.print("Concentration O3 : ");
PPBO2 = MQ131.getO3(PPB);
Serial.print(PPBO2);
Serial.println(" ppb");
Serial.print("Concentration O3 : ");
MGM3O2 = MQ131.getO3(MG_M3);
Serial.print(MGM3O2);
Serial.println(" mg/m3");
Serial.print("Concentration O3 : ");
UGM3O2 = MQ131.getO3(UG_M3);
Serial.print(UGM3O2);
Serial.println(" ug/m3");
}
void setup()
{
Serial.begin(PC_BAUDRATE);
// wait for the Arduino serial (on your PC) to connect
// please, open the Arduino serial console (right top corner)
// note that the port may change after uploading the sketch
// COMMENT OUT FOR USAGE WITHOUT A PC!
// while(!Serial);
Serial.println("openCanSat PRO");
Serial.print("Node ");
Serial.print(MYNODEID,DEC);
Serial.println(" ready");
// begin communication with the BME280 on the previously specified address
// print an error to the serial in case the sensor is not found
if (!bme.begin(BME280_ADDRESS_OPEN_CANSAT))
{
isBmeOk = false;
Serial.println("Could not find a valid BME280 sensor, check wiring!");
return;
}
// begin communication with the INA219
ina219.begin();
// check of Gps is connected
Wire.beginTransmission(0x42); // 42 is addres of GPS
int error = Wire.endTransmission();
if (error != 0)
{
isGpsConnected = false;
}
// begin communication with gps
gps.begin();
// Uncomment when you want to see debug prints from GPS library
// gps.debugPrintOn(57600);
if(!radio.initialize(FREQUENCY, MYNODEID, NETWORKID))
{
isRadioOk = false;
Serial.println("RFM69HW initialization failed!");
}
else
{
radio.setFrequency(FREQUENCYSPECIFIC);
radio.setHighPower(true); // Always use this for RFM69HW
}
pinMode(D13_led_pin, OUTPUT);
}
void loop()
{
pinMode(SS, OUTPUT);
digitalWrite(SS, HIGH);
pinMode(DcPin, OUTPUT);
pinMode(O2Pin, OUTPUT);
digitalWrite(DcPin, HIGH);
digitalWrite(O2Pin, HIGH);
delay(10000);
OZONE2CLICKCalibrate();
OZONE2CLICKMeasure();
}
It looks the code opening the SPI connection is commented out:
MQ131.begin(pinSS, pinRDY, O2Pin, LOW_CONCENTRATION, 10000);
You need to configure the SPI connection to get any data from your device.
Refer to reference code from the manufacturer or library you're using to make sure your programming against it correctly.
Please format your code with predictable spacing. This is pretty hard to read.
Since you're using C++, prefer to use:
constexpr <type> NAME = <value>;
rather than macros:
#define NAME (<value>)
Since this is a bare metal compilation, using return in the setup() or loop() functions does not stop them. You probably want something more like while (true) {}. This will loop the code indefinitely, rather than proceed in a bad state.
i.e.:
void stop_forever() {
Serial.println("fatal error detected, stoping forever.");
while (true) {}
}
// then, use it later:
// ...
if (error) {
stop_forever();
}
// ...