Script hangs up arduino

dear community

Arudino Uno R3 serial USB Rasbperry Pi 4B
Weather Data Readout and Communication (wind, temp, rain)
After two days the serial monitor cant show values, because the Uno froze.
After turn on off supply the setup works again..

Any problem with my script maybe? Does one see my mistake?

#include <cactus_io_BME280_SPI.h>
#include <SPI.h>


#define BME_SCK 13     // Serial Clock
#define BME_MISO 11    // Serial Data In
#define BME_MOSI 12    // Serial Data Out
#define BME_CS 10      // Chip Select

#define sensorPower 7
#define sensorPin 8

BME280_SPI bme(BME_CS,BME_MOSI,BME_MISO,BME_SCK); // BME280_SPI bme(BME_CS); (SPI)

#include "TimerOne.h"
#include <math.h>

#define WindSensorPin (2) // The pin location of the anemometer sensor
#define WindVanePin (A4) // The pin the wind vane sensor is connected to
#define VaneOffset 0; // define the anemometer offset from magnetic north

int VaneValue; // raw analog value from wind vane
int Direction; // translated 0 - 360 direction
int CalDirection; // converted value with offset applied
int LastValue; // last direction value

volatile bool IsSampleRequired; // this is set true every 2.5s. Get wind speed
volatile unsigned int TimerCount; // used to determine 2.5sec timer count
volatile unsigned long Rot; // cup rotation counter used in interrupt routine
volatile unsigned long Rotations; 
volatile unsigned long ContactBounceTime; // Timer to avoid contact bounce in isr

float WindSpeed; // speed miles per hour

char rot[7];
char hu[7];
char dir[7];
char tc[7];
char tf[7];
char vv[7];
char pre[7];
char val[7];




void setup() {

  Serial.begin(4800);
  pinMode(sensorPower, OUTPUT); // rain

  // Initially keep the sensor OFF
  digitalWrite(sensorPower, LOW); //rain
  pinMode(WindSensorPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(WindSensorPin), isr_rotation, FALLING);

  LastValue = 0;

  IsSampleRequired = false;

  TimerCount = 0;
  


  
  //Serial.println("Bosch BME280 Pressure - Humidity - Temp Sensor | cactus.io");
  //Serial.println("Speed (MPH)\tKnots\tDirection\tStrength");


  if (!bme.begin()) {
  Serial.println("Could not find a valid BME280 sensor, check wiring!");
  while (1);
  }

  // bme.setTempCal(1);// Sensor was reading high so offset by 1 degree C

  // Serial.println("Rotations\tVaneValue\tDirection\tPressure\tHumdity\t\tTemp\t\tTemp");
}

void loop() {
 
  
  Rotations = 0; 
  sei(); // Enables interrupts
  delay (3000); // Wait 3 seconds to average
  cli(); // Disable interrupts

// convert to mp/h using the formula V=P(2.25/T)
// V = P(2.25/3) = P * 0.75

  WindSpeed = Rotations * 0.75;

  bme.readSensor();

  float temp_c = bme.getTemperature_C();
  float hum = bme.getHumidity();
  float pres = bme.getPressure_MB();
  float temp_f = bme.getTemperature_F();
  int val = readSensor();

  VaneValue = analogRead(A4);
  Direction = map(VaneValue, 0, 1023, 0, 359);
  CalDirection = Direction + VaneOffset;


  if(CalDirection > 360)
  CalDirection = CalDirection - 360;

  if(CalDirection < 0)
  CalDirection = CalDirection + 360;

  if (Direction == 360) Direction = 0;

  //char buffer[70];
  //sprintf{buffer, "Pressure %d mb

  //dtostrf(Rotations,5,2,rot);
  //dtostrf(VaneValue,7,2,vv);
  //dtostrf(CalDirection,7,2,dir);
  //dtostrf(pres,7,2,pre);
  //dtostrf(hum,7,2,hu);
  //dtostrf(temp_c,7,2,tc);
  //dtostrf(temp_f,7,2,tf);

   

 //char buffer[30];
 //sprintf(buffer, "%i; %i; %i; %d; %d; %d; %d", Rotations, VaneValue, CalDirection, pres, hum, temp_c, temp_f);
 //Serial.println(buffer);
 
  Serial.print(Rotations); Serial.print(",");//Serial.print("\t\t");
  Serial.print(VaneValue); Serial.print(",");//Serial.print("\t\t");
  Serial.print(CalDirection); Serial.print(",");//Serial.print(" °\t\t");
  Serial.print(pres); Serial.print(",");//Serial.print(" mb\t"); // Pressure in millibars
  Serial.print(hum); Serial.print(",");//Serial.print(" %\t\t");
  Serial.print(temp_c); Serial.print(",");//Serial.print(" *C\t");
  Serial.print(val);  Serial.print("\n");//Serial.println(" *F\t");






  // Add a 2 second delay.
  delay(3000); //just here to slow down the output.
}


// This is the function that the interrupt calls to increment the rotation count
void isr_rotation () {

  if ((millis() - ContactBounceTime) > 15 ) { // debounce the switch contact.
    Rotations++;
    ContactBounceTime = millis();
}
}

//  This function returns the rainsensor output
int readSensor() {
  digitalWrite(sensorPower, HIGH);  // Turn the sensor ON
  delay(10);              // Allow power to settle
  int val = digitalRead(sensorPin); // Read the sensor output
  digitalWrite(sensorPower, LOW);   // Turn the sensor OFF
  return val;             // Return the value
}

Your topic was MOVED to its current forum category which is more appropriate than the original as it has nothing to do with Installation and Troubleshooting of the IDE

What made you think that it did ?

please when posting code, clean it up...it's full of unused variables some with confusing names between local and global variables like

char val[7];

and

  int val = readSensor();

and you have lots of things commented out, or some lines with stupid comments

  // Add a 2 second delay.
  delay(3000);

help us help you, post something cleaned up..

I would add a bunch of debug output, with a Serial.flush(); after each. Before and after each function call would be good. You can use the __FILE__ and __LINE__ macros to automate the contents of the messages.

After two days, when the output stops, you will see where your code was when it stopped.

Serial.println(__FILE__ __LINE__); Serial.flush();

sorry, cleaned version:

#include <cactus_io_BME280_SPI.h>
#include <SPI.h>
#include "TimerOne.h"
#include <math.h>

//BME280
#define BME_SCK 13     // Serial Clock
#define BME_MISO 11    // Serial Data In
#define BME_MOSI 12    // Serial Data Out
#define BME_CS 10      // Chip Select
//RAIN
#define sensorPower 7
#define sensorPin 8
//WIND
#define WindSensorPin (2) // The pin location of the anemometer sensor
#define WindVanePin (A4) // The pin the wind vane sensor is connected to
#define VaneOffset 0; // define the anemometer offset from magnetic north


BME280_SPI bme(BME_CS,BME_MOSI,BME_MISO,BME_SCK); // BME280_SPI bme(BME_CS); (SPI)

int VaneValue; // raw analog value from wind vane
int Direction; // translated 0 - 360 direction
int CalDirection; // converted value with offset applied
int LastValue; // last direction value

volatile bool IsSampleRequired; // this is set true every 2.5s. Get wind speed
volatile unsigned int TimerCount; // used to determine 2.5sec timer count
volatile unsigned long Rot; // cup rotation counter used in interrupt routine
volatile unsigned long Rotations; 
volatile unsigned long ContactBounceTime; // Timer to avoid contact bounce in isr

float WindSpeed; // speed miles per hour

char rot[7];
char hu[7];
char dir[7];
char tc[7];
char tf[7];
char vv[7];
char pre[7];
char val[7]; //rain




void setup() {

  Serial.begin(4800);

  pinMode(sensorPower, OUTPUT); // rain
  digitalWrite(sensorPower, LOW); //rain
  pinMode(WindSensorPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(WindSensorPin), isr_rotation, FALLING);

  LastValue = 0;
  IsSampleRequired = false;
  TimerCount = 0;
  

  if (!bme.begin()) {
  Serial.println("Could not find a valid BME280 sensor, check wiring!");
  while (1);
  }
}

void loop() {

  bme.readSensor();
 
  Rotations = 0; 
  sei(); // Enables interrupts
  delay (3000); // Wait 3 seconds to average
  cli(); // Disable interrupts

  VaneValue = analogRead(A4);
  Direction = map(VaneValue, 0, 1023, 0, 359);

  float temp_c = bme.getTemperature_C();
  float hum = bme.getHumidity();
  float pres = bme.getPressure_MB();
  float temp_f = bme.getTemperature_F();
  int val = readSensor(); //rain


 
  Serial.print(Rotations); Serial.print(",");//Serial.print("\t\t");
  Serial.print(VaneValue); Serial.print(",");//Serial.print("\t\t");
  Serial.print(CalDirection); Serial.print(",");//Serial.print(" °\t\t");
  Serial.print(pres); Serial.print(",");//Serial.print(" mb\t"); // Pressure in millibars
  Serial.print(hum); Serial.print(",");//Serial.print(" %\t\t");
  Serial.print(temp_c); Serial.print(",");//Serial.print(" *C\t");
  Serial.print(val);  Serial.print("\n");//Serial.println(" *F\t");

  // Add a 3 second delay.
  delay(3000); //just here to slow down the output.
}


// This is the function that the interrupt calls to increment the rotation count
void isr_rotation () {

  if ((millis() - ContactBounceTime) > 15 ) { // debounce the switch contact.
    Rotations++;
    ContactBounceTime = millis();
}
}

//  This function returns the rainsensor output
int readSensor() {
  digitalWrite(sensorPower, HIGH);  // Turn the sensor ON
  delay(10);              // Allow power to settle
  int val = digitalRead(sensorPin); // Read the sensor output
  digitalWrite(sensorPower, LOW);   // Turn the sensor OFF
  return val;             // Return the value
}

current output after reboot system

are those used at all?

char rot[7];
char hu[7];
char dir[7];
char tc[7];
char tf[7];
char vv[7];
char pre[7];
char val[7]; //rain

why do you do this in the loop(). Why don't you keep the interrupts on all time?

  sei(); // Enables interrupts
  delay (3000); // Wait 3 seconds to average
  cli(); // Disable interrupts
1 Like

good point Jackson, I deletd the char row. there was a different approach were i used them.

For the Windmeter i just used this code:

http://cactus.io/hookups/weather/anemometer/davis/hookup-arduino-to-davis-anemometer-wind-speed

What would you recommend Jackson?
Thanks for reply !

I would not mess with interrupts for such a long time (it impacts millis, delay, ...) - let them come in and count the number of ticks from your wind meter all the time

I would maintain a variable that tells me when 3s has elapsed and I would do a short critical section with interrupts disabled to copy and reset the counter and then reactivate the interrupts

https://github.com/Bra1nsen/SkyCam/blob/main/Weather/rain__wind_bme280.ino

would you please show in me code? Of course i will spend you a coffee via paypal if it works =)!

where did you get cactus_io_BME280_SPI from?

this would be the idea for the code (modified their example)


const byte windSensorPin = 2;   // The pin location of the anemometer sensor

volatile unsigned long rotationCounter; // cup rotation counter used in interrupt routine
unsigned long lastSampleTime;
const unsigned long samplingPeriod = 3000ul;

// This is the function that the interrupt calls to increment the rotation count
void isr_rotation () {
  static volatile unsigned long lastRecordingTime; // Timer to avoid contact bounce in interrupt routine

  if ((millis() - lastRecordingTime) > 15 ) { // debounce the switch contact.
    rotationCounter++;
    lastRecordingTime = millis();
  }
}

void setup() {
  pinMode(windSensorPin, INPUT);
  Serial.begin(115200);

  Serial.println("\nWind Speed Test");
  Serial.println("rotationCounter\tMPH");
  attachInterrupt(digitalPinToInterrupt(windSensorPin), isr_rotation, FALLING);
}

void loop() {
  unsigned long now = millis();
  if (now - lastSampleTime >= samplingPeriod) {
    // time to take a sample

    // -------------------------------------------------------
    // critical section to access the shared variable
    // -------------------------------------------------------
    noInterrupts();
    unsigned long rotationCounterCopy =  rotationCounter;
    rotationCounter = 0;
    interrupts();
    // -------------------------------------------------------
    // end of critcal section
    // -------------------------------------------------------

    // convert to mp/h using the formula V=P x 2.25 / ∆T  with ∆T the sampling period in seconds, so V = P x 2250 / ∆T with ∆t in ms
    double windSpeed = rotationCounterCopy * (2250.0 / (now - lastSampleTime)); // speed miles per hour

    // remember when we took the last sample
    lastSampleTime = now;


    Serial.print(rotationCounterCopy);
    Serial.print("\t\t");
    Serial.println(windSpeed);
  }
}

Jackson, so?

//DAVIS WIND http://cactus.io/hookups/weather/anemometer/davis/hookup-arduino-to-davis-anemometer
//BME280 http://cactus.io/hookups/sensors/barometric/bme280/hookup-arduino-to-bme280-barometric-pressure-sensor-spi
//RAIN https://create.arduino.cc/projecthub/MisterBotBreak/how-to-use-a-rain-sensor-bcecd9

#include <cactus_io_BME280_SPI.h>
#include <SPI.h>
#include "TimerOne.h"
#include <math.h>

#define BME_SCK 13     // Serial Clock
#define BME_MISO 11    // Serial Data In
#define BME_MOSI 12    // Serial Data Out
#define BME_CS 10      // Chip Select

#define WindSensorPin (2) // The pin location of the anemometer sensor
#define WindVanePin (A4) // The pin the wind vane sensor is connected to
#define VaneOffset 0; // define the anemometer offset from magnetic north

BME280_SPI bme(BME_CS,BME_MOSI,BME_MISO,BME_SCK); // BME280_SPI bme(BME_CS); (SPI)

int VaneValue; // raw analog value from wind vane
int Direction; // translated 0 - 360 direction
int CalDirection; // converted value with offset applied
int LastValue; // last direction value

volatile bool IsSampleRequired; // this is set true every 2.5s. Get wind speed
volatile unsigned int TimerCount; // used to determine 2.5sec timer count
volatile unsigned long Rot; // cup rotation counter used in interrupt routine
volatile unsigned long Rotations; 
volatile unsigned long ContactBounceTime; // Timer to avoid contact bounce in isr

float WindSpeed; // speed miles per hour

const int capteur_D = 3; //RAIN
const int capteur_A = A0; //RAIN

const byte windSensorPin = 2;   // The pin location of the anemometer sensor

volatile unsigned long rotationCounter; // cup rotation counter used in interrupt routine
unsigned long lastSampleTime;
const unsigned long samplingPeriod = 3000ul;

void setup() {

  Serial.begin(4800);
  
  pinMode(capteur_D, INPUT); //rain
  pinMode(capteur_A, INPUT); //rain
  
  pinMode(WindSensorPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(WindSensorPin), isr_rotation, FALLING);

  LastValue = 0;
  IsSampleRequired = false;
  TimerCount = 0;
 
  if (!bme.begin()) {
  Serial.println("Could not find a valid BME280 sensor, check wiring!");
  while (1);
  }
}

void loop() {
  
  unsigned long now = millis();
  if (now - lastSampleTime >= samplingPeriod) {
    // time to take a sample

    // -------------------------------------------------------
    // critical section to access the shared variable
    // -------------------------------------------------------
    noInterrupts();
    unsigned long rotationCounterCopy =  rotationCounter;
    rotationCounter = 0;
    interrupts();
    // -------------------------------------------------------
    // end of critcal section
    // -------------------------------------------------------


    // remember when we took the last sample
    lastSampleTime = now;
  

    bme.readSensor();

    float temp_c = bme.getTemperature_C();
    float hum = bme.getHumidity();
    float pres = bme.getPressure_MB();
    float temp_f = bme.getTemperature_F();
    int val = analogRead(capteur_A);

    VaneValue = analogRead(A4);
    Direction = map(VaneValue, 0, 1023, 0, 359);
    CalDirection = Direction + VaneOffset;

 
    Serial.print(rotationCounterCopy); Serial.print(",");//Serial.print("\t\t");
    Serial.print(VaneValue); Serial.print(",");//Serial.print("\t\t");
    Serial.print(CalDirection); Serial.print(",");//Serial.print(" °\t\t");
    Serial.print(pres); Serial.print(",");//Serial.print(" mb\t"); // Pressure in millibars
    Serial.print(hum); Serial.print(",");//Serial.print(" %\t\t");
    Serial.print(temp_c); Serial.print(",");//Serial.print(" *C\t");
    Serial.print(val);  Serial.print("\n");//Serial.println(" *F\t");



  // Add a 3 second delay.
  delay(3000); //just here to slow down the output.
  }
}

// This is the function that the interrupt calls to increment the rotation count
void isr_rotation () {
  static volatile unsigned long lastRecordingTime; // Timer to avoid contact bounce in interrupt routine

  if ((millis() - lastRecordingTime) > 15 ) { // debounce the switch contact.
    rotationCounter++;
    lastRecordingTime = millis();
  }
}

I would probably write code without any delay and I don't know what cactus_io_BME280_SPI is, so not sure what it does

Acutally I use the raw values from the windsensor for training a neuronal network.
Calculating the windspeed in terms of human standards one has to integrate a file, so that the code is looking up a calibrated wind speed value in that table using these raw 2 values.

you can share your paypal link. i have a lot thing to do. but if your interessted in adding that feature, i would finance that.

Do you have experience with flux and grafana jackson?

cheers

I've enough coffee at home, thanks for the offer. Happy if that was helpful

I've used flux and grafana in the past for a few projects but would not call me an expert. I'm contributing here where I can for the fun of it - not looking at having deadlines or constraints :slight_smile:

ok all right jackson. thank you for your help.
really honored that you help so selflessly. hopefully it will work reliable..

so I would go for this after more clean up of unused stuff

//DAVIS WIND http://cactus.io/hookups/weather/anemometer/davis/hookup-arduino-to-davis-anemometer
//BME280 http://cactus.io/hookups/sensors/barometric/bme280/hookup-arduino-to-bme280-barometric-pressure-sensor-spi
//RAIN https://create.arduino.cc/projecthub/MisterBotBreak/how-to-use-a-rain-sensor-bcecd9

#include <cactus_io_BME280_SPI.h>

#define BME_SCK 13     // Serial Clock
#define BME_MISO 11    // Serial Data In
#define BME_MOSI 12    // Serial Data Out
#define BME_CS 10      // Chip Select
BME280_SPI bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // BME280_SPI bme(BME_CS); (SPI)

const byte WindVanePin = A4;  // The pin the wind vane sensor is connected to
const byte VaneOffset = 0;    // define the anemometer offset from magnetic north


const byte capteurDPin = 3;       // RAIN
const byte capteurAPin = A0;      // RAIN
const byte windSensorPin = 2;     // The pin location of the anemometer sensor

volatile unsigned long rotationCounter; // cup rotation counter used in interrupt routine
unsigned long lastSampleTime;
const unsigned long samplingPeriod = 3000ul;

// This is the function that the interrupt calls to increment the rotation count
void isr_rotation () {
  static volatile unsigned long lastRecordingTime; // Timer to avoid contact bounce in interrupt routine

  if ((millis() - lastRecordingTime) > 15 ) { // debounce the switch contact.
    rotationCounter++;
    lastRecordingTime = millis();
  }
}

void setup() {
  pinMode(capteurDPin, INPUT); //rain
  pinMode(capteurAPin, INPUT); //rain
  pinMode(windSensorPin, INPUT);

  Serial.begin(4800);

  if (!bme.begin()) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (true);
  }

  attachInterrupt(digitalPinToInterrupt(windSensorPin), isr_rotation, FALLING);
}


void loop() {
  unsigned long now = millis();
  
  if (now - lastSampleTime >= samplingPeriod) {     // time to take a sample
    // -------------------------------------------------------
    // critical section to access the shared variable
    // -------------------------------------------------------
    noInterrupts();
    unsigned long rotationCounterCopy =  rotationCounter;
    rotationCounter = 0;
    interrupts();
    // -------------------------------------------------------
    // end of critcal section
    // -------------------------------------------------------

    // remember when we took the last sample
    lastSampleTime = now;

    bme.readSensor();
    float temp_c = bme.getTemperature_C();
    float hum = bme.getHumidity();
    float pres = bme.getPressure_MB();
    float temp_f = bme.getTemperature_F();
    int valA = analogRead(capteurAPin);

    int VaneValue = analogRead(A4);
    int Direction = map(VaneValue, 0, 1023, 0, 359);
    int CalDirection = Direction + VaneOffset;

    Serial.print(rotationCounterCopy);  Serial.write(',');
    Serial.print(VaneValue);            Serial.write(',');
    Serial.print(CalDirection);         Serial.write(',');
    Serial.print(pres);                 Serial.write(',');
    Serial.print(hum);                  Serial.write(',');
    Serial.print(temp_c);               Serial.write(',');
    Serial.print(valA);                 Serial.write('\n');
  } // end sampling
}

As you now include the printing in the sampling loop you'll get data every 3s or so

I removed many #include as they should be included automagically by the IDE


why do you use 4800 for the baud rate ? do you have some wireless component attached to the Serial port?

yes but you have to #define WindSensorPin (2) // The pin location of the anemometer sensor

i saved your file, its running hot now (Y)