I am in the process of implementing power down alerting system suing Arduino UNO and ZMPT101B Single phase relay.
My code as follows,
#include <Filters.h> //Easy library to do the calculations
float testFrequency = 50; // test signal frequency (Hz)
float windowLength = 40.0/testFrequency; // how long to average the signal, for statistist
int Sensor = 0; //Sensor analog input, here it's A0
float intercept = -0.04; // to be adjusted based on calibration testing
float slope = 0.0405; // to be adjusted based on calibration testing
float current_Volts; // Voltage
unsigned long printPeriod = 1000; //Refresh rate
unsigned long previousMillis = 0;
void setup() {
Serial.begin( 9600 ); // start the serial port
}
void loop() {
RunningStatistics inputStats; //Easy life lines, actual calculation of the RMS requires a load of coding
inputStats.setWindowSecs( windowLength );
while( true ) {
Sensor = analogRead(A0); // read the analog in value:
inputStats.input(Sensor); // log to Stats function
if((unsigned long)(millis() - previousMillis) >= printPeriod) {
previousMillis = millis(); // update time every second
Serial.print( "\n" );
current_Volts = intercept + slope * inputStats.sigma(); //Calibartions for offset and amplitude
current_Volts= current_Volts*(40.3231); //Further calibrations for the amplitude
Serial.print( "\tVoltage: " );
Serial.print( current_Volts ); //Calculation and Value display is done the rest is if you're using an OLED display
if (current_Volts <229) {
test_loop();
}
}
}
}
void test_loop(){
Serial.print( "Warning!! Server Room Power Down" );
delay(1000);
}
I am getting the correct voltage reading.
But when power down it says power down.
But when power got up it still shows power down with older reading.
I think the reason for this because my code unable to stop the loop.
And if I remove the delay (1000) in test_loop function it works,
But my intention to use this sms alerting system and for that I need this delay to stop unnecessary alerts.
My code for SMS Alerting,
Serial.print( "\tVoltage: " );
Serial.print( current_Volts ); //Calculation and Value display is done the rest is if you're using an OLED display
if (current_Volts <229) {
SendMessage();
}
void test_loop() {
mySerial.println("AT+CMGF=1"); //Sets the GSM Module in Text Mode
delay(1000); // Delay of 1000 milli seconds or 1 second
mySerial.println("AT+CMGS=\"xxxxxxxxx\"\r"); // Replace x with mobile number
delay(1000);
mySerial.println("Warning!! Server Room Power Down");
delay(100);
mySerial.println((char)26);// ASCII code of CTRL+Z
delay(150000);
mySerial.println("AT+CMGD=2");
}
This code works for the very first outage but after power up also it send power down.
First code of Serial.print is used fro debugging.
Kindly help.
Thanks to the Arduino Forum User: leongjerland
I was able to fix the issue.
The code as below,
if (current_Volts < 229) {
if (!alarmSent) {
test_loop();
alarmSent = true;
}
}
else {
alarmSent = false;
}
}
Try seeing with a voltmeter what the voltage is at the A0 pin in the good and the bad case. You don't need to decode the voltage, just see if it the sensor is working as you expect.
Related
I built an app to observe real-time graph. I set the sampling rate to 256hz in my Arduino code. I gave the output of 100hz through a function generator, but I obtained a random waveform instead of the sine waveform.
this is my Arduino code:
#include <SoftwareSerial.h> //import Software Serial library
SoftwareSerial myStream(0, 1); //pins for Rx and Tx respectively
int ECG;
void setup()
{
// put your setup code here, to run once:
pinMode(A0, INPUT); //LDR
myStream.begin(115200);
Serial.begin(9600);
}
void loop()
{
ECG = analogRead(A0);
Serial.println(ECG);
if (myStream.available() > 0)
{
char re = myStream.read();
switch (re)
{
case 'E':
start();
break;
}
}
//about 256Hz sample rate
delayMicroseconds(3900);
}
void start()
{
while (1)
{
myStream.print('s');
myStream.print(floatMap(analogRead(ECG), 0, 1023, 0, 255), 2);
//about 256Hz sample rate
delayMicroseconds(3900);
if (Serial.available() > 0)
{
if (Serial.read() == 'Q')
return;
}
}
}
float floatMap(float x, float inMin, float inMax, float outMin, float outMax)
{
return (x - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
}
This is my circuit diagram. In addition, I connected the oscilloscope output to A0 and common ground.
enter image description here
How can I get the sine waveform in my app.Any help on this would be greatly appreciated.
With your ~ 256 Hz sampling rate you just get about 2 asynchronous readings per period of a 100 Hz source.
analogRead adds (100 .. 150 µs on a 16 MHz Arduino) a considerable jitter to your delay.
Not sure about SoftwareSerial sending #115200. (receive won't work well at that speed)
And float is slow, too.
Not sure what you expect.
Check the raw data first:
void setup() {
Serial.begin(115200); // allows for 10 char/ms
}
void loop() {
static unsigned long oldmillis;
if (millis() != oldmillis) {
oldmillis = millis();
// 1 kHz sample rate :
int ECG = analogRead(A0)*100L / 1024;
Serial.println(ECG); // 0 .. 99
}
}
Perhaps add your start/stop communication or check with Arduino SerialPlotter.
When that's ok, test if you get those numbers via bluetooth to your app...
I have an issue trying to send some serial data through tx and rx to another arduino through a HC05 bluetooth module.
The overall project is developing a hybrid go kart and using the arduino as a simple ECU unit with a PID speed control over the PWM output controlling a DC motor. I have been working the project in steps and have go as far as setting up a footpedal with the arduino and controlling the electronic speed controller (ESC) directly. I have added a simple PID function to this along with a simple hall sensor to detect the speed and does require tuning but works great so far. Now the problem comes when I try to send data across over serial ports.
I have had the bluetooth modules connected with to separate arduinos and have successfully managed to send over data from one arduino with a pot input to another with a 3.5 inch TFT screen. When I try to integrate the master side of the project to the PID controlled DC motor the system freezes. I have since then removed the PID control and gone back to direct control and it still fails, i have tried commenting out the interrupt sequence for the encoder and put a static value for RPM and still freezes. the sending sequence works if I don't attempt to use any digital outputs. I am really confused. The code I have gone down to to try and debug this can be found below. This is not the full code and has been chopped to pieces to try and eliminate this fault. however in this code below, if I comment out the sendData function the system works and the motor spins with relative speed to the pedal input. as soon as I try to send the data the system runs for a seconds then freezes. the data is still being sent and the static readings are showing just the digital output seizes to work.
#include <TimerOne.h>
int previous = 0;
int Tavg = 0; // the average
int Tout = 0;
int throttle = A0;
const int numReadings = 10;
int readings[numReadings]; // the readings from the analog input
int readIndex = 0; // the index of the current reading
int total = 0; // the running total
int ESCPin = 5;
unsigned int counter=0;
int RPM;
long Time = 0;
long ReadInt = 0;
void docount() // counts from the speed sensor
{
counter++; // increase +1 the counter value
}
void timerIsr()
{
Timer1.detachInterrupt(); //stop the timer
Serial.print("Motor Speed: ");
RPM = (counter*75 ); // RPM= counterx10*60/8 (x10 for second, 8 counts in encoder, 60 minutes === 75x counter)
Serial.print(RPM);
Serial.println(" Rotation per min"); Serial.print(Tout);Serial.print("= "); Serial.print(Tout*0.01961);Serial.println("V");
counter=0; // reset counter to zero
Timer1.attachInterrupt( timerIsr ); //enable the timer
}
void ReadEnc (){
Timer1.initialize(100000); // set timer for 0.1sec
attachInterrupt(0, docount, RISING); // increase counter when speed sensor pin goes High
Timer1.attachInterrupt( timerIsr ); // enable the timer
}
void sendData(){
if (Serial.available()>0) {
if (Serial.read() == 0){
//Serial.println(sendChars);
int RPMout = RPM;
Serial.write("<");
//delay(2);
//Serial.write(sendChars);
Serial.write("Data is,");
//delay(2);
Serial.write( itoa (RPMout, 4,10));
//delay(2);
Serial.write(", 30, 48.35");
//delay(2);
Serial.write(">");
//delay(10);
Serial.println("");
}
}
}
void setup()
{
Serial.begin(9600);
pinMode(2, INPUT_PULLUP); // internal pullup input pin 2
pinMode(ESCPin, OUTPUT);
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
readings[thisReading] = 0; }
Time = millis();
ReadInt = -100;
}
void ReadSensor (){
// get the sensor value
total = total - readings[readIndex];
// read from the sensor:
readings[readIndex] = analogRead(throttle);
//Serial.println(readings[readIndex]);
// add the reading to the total:
total = total + readings[readIndex];
// advance to the next position in the array:
readIndex = readIndex + 1;
// if we're at the end of the array...
if (readIndex >= numReadings) {
// ...wrap around to the beginning:
readIndex = 0;
}
// calculate the average:
Tavg = total / numReadings;
}
void loop(){
ReadSensor();
ReadEnc();
RPM = 1800;
Tout = map(Tavg, 180, 860, 0, 200);
if (Tout>0){
analogWrite(ESCPin, Tout);
}
if (Time > ReadInt + 5000) {
sendData (); // when this is commented it works fine, tried moving it everywhere
ReadInt = Time;
}
Time = millis();
}
If anyone has any ideas please let me know, and I know I probably haven't explained my problem well so if their is any questions or more details needed please ask.
Second parameter of itoa should be a pointer to output bufffer. but you do not need itoa. use Serial.print(RPM);. For string the print and write functions are the same, but for number print has a version for int
Can someone help me with this Sigfox setup?
What have I done wrong? :-)
The only thing I wanted to achieve was to post the internal temperature and the status to the sigfox backend.
Each 15min, the data would be posted.
A configured an email from the service showing the temperature in degrees Celcius.
Posting to the backend is working.
However the email message and the data seems not to correspond.
When running the code in debug mode. The temperature is showing correctly in degrees Celcius.
Is there a manual available?
Code Arduino MKR FOX 1200
Temp.ino
#include <ArduinoLowPower.h>
#include <SigFox.h>
#include "conversions.h"
// Set oneshot to false to trigger continuous mode when you finisched setting up the whole flow
int oneshot = false;
#define STATUS_OK 0
/*
ATTENTION - the structure we are going to send MUST
be declared "packed" otherwise we'll get padding mismatch
on the sent data - see http://www.catb.org/esr/structure-packing/#_structure_alignment_and_padding
for more details
*/
typedef struct __attribute__ ((packed)) sigfox_message {
int16_t moduleTemperature;
uint8_t lastMessageStatus;
} SigfoxMessage;
// stub for message which will be sent
SigfoxMessage msg;
void setup() {
if (oneshot == true) {
// Wait for the serial
Serial.begin(115200);
while (!Serial) {}
}
if (!SigFox.begin()) {
// Something is really wrong, try rebooting
// Reboot is useful if we are powering the board using an unreliable power source
// (eg. solar panels or other energy harvesting methods)
reboot();
}
//Send module to standby until we need to send a message
SigFox.end();
if (oneshot == true) {
// Enable debug prints and LED indication if we are testing
SigFox.debug();
}
}
void loop() {
// Every 15 minutes, read all the sensor and send the data
// Let's try to optimize the data format
// Only use floats as intermediate representaion, don't send them directly
//sensors_event_t event;
// Start the module
SigFox.begin();
// Wait at least 30ms after first configuration (100ms before)
delay(100);
// We can only read the module temperature before SigFox.end()
float temperature = SigFox.internalTemperature();
msg.moduleTemperature = convertoFloatToInt16(temperature, 60, -60);
if (oneshot == true) {
Serial.println("Internal temp: " + String(temperature));
}
// Clears all pending interrupts
SigFox.status();
delay(1);
SigFox.beginPacket();
SigFox.write((uint8_t*)&msg, 12);
msg.lastMessageStatus = SigFox.endPacket();
if (oneshot == true) {
Serial.println("Status: " + String(msg.lastMessageStatus));
}
SigFox.end();
if (oneshot == true) {
// spin forever, so we can test that the backend is behaving correctly
while (1) {}
}
//Sleep for 15 minutes
LowPower.sleep(1 * 60 * 1000);
}
void reboot() {
NVIC_SystemReset();
while (1);
}
Conversion.h
#define UINT16_t_MAX 65536
#define INT16_t_MAX UINT16_t_MAX/2
int16_t convertoFloatToInt16(float value, long max, long min) {
float conversionFactor = (float) (INT16_t_MAX) / (float)(max - min);
return (int16_t)(value * conversionFactor);
}
uint16_t convertoFloatToUInt16(float value, long max, long min = 0) {
float conversionFactor = (float) (UINT16_t_MAX) / (float)(max - min);
return (uint16_t)(value * conversionFactor);
}
Settings Sigfox Backend - email Callbacks
With the current convertoFloatToInt16, it will not be possible to display the real temperature in an email directly from Sigfox Backend.
You either need to use a callback from Sigfox Backend to a server that implements convertoFloatToUInt16 and then sends the email, or send the temperature in a format that the Sigfox Backend can decode natively (32-bit float is probably the most suitable).
I have and arduino sketch that needs to do several operations on a timed schedule using the TimeAlarms.h library. However, one of the operations, reading a hall sensor via interrupts, seems to interact poorly with the TimeAlarms library.
I'm using the TimeAlarms library from here: http://www.pjrc.com/teensy/td_libs_TimeAlarms.html
And have adapted the hall sensor script from here:
http://www.seeedstudio.com/wiki/G3/4_Water_Flow_sensor
I can run the hall sensor code on it own fine. However, when I try to run the hall sensor code along with Alarm.timerRepeat it hangs after entering the check_flow function.
Running the code below outputs only enter CF and then hangs. The same occurs if you try the check_flow_alarm_delay function instead, which uses the TimeAlarm version of Delay.
However, if you comment out Alarm.timerRepeat(10, showseconds); in setup
and Alarm.delay(0); in loop the hall sensor works fine.
Strangely, if you comment out sei(); and cli(); in the check_flow function the script works fine, and seems to count properly with the hall sensor. Why would this work? And should I be concerned that I'm not actively setting the time between sei() and cli(), leading to reliability issues in the sensor?
Note: you should be able to run the code without actually having a hall sensor, the output will just be 0 L/hr.
// reading liquid flow rate using Seeeduino and Water Flow Sensor from Seeedstudio.com
// Code adapted by Charles Gantt from PC Fan RPM code written by Crenn #thebestcasescenario.com
// http:/themakersworkbench.com http://thebestcasescenario.com http://seeedstudio.com
#include <Time.h>
#include <TimeAlarms.h>
#include <Wire.h>
volatile int NbTopsFan; //measuring the rising edges of the signal
int Calc;
int hallsensor = 2; //The pin location of the sensor
void rpm () //This is the function that the interupt calls
{
NbTopsFan++; //This function measures the rising and falling edge of the hall effect sensors signal
}
void setup() //
{
Serial.begin(9600); //This is the setup function where the serial port is initialised,
pinMode(hallsensor, INPUT); //initializes digital pin 2 as an input
attachInterrupt(0, rpm, RISING); //and the interrupt is attached
Alarm.timerRepeat(10, showseconds);
}
void loop ()
{
// Serial.println( second() );
// stalls at enter CF
// check_flow();
// stalls at enter CF
check_flow_alarm_delay();
Alarm.delay(0);
}
void showseconds ()
{
Serial.println( second() );
}
void check_flow ()
{
Serial.println("enter CF");
int Calc;
NbTopsFan = 0; //Set NbTops to 0 ready for calculations
// sei(); //Enables interrupts
delay(1000); //Wait 1 second
// cli(); //Disable interrupts
Calc = (NbTopsFan * 60 / 5.5); //(Pulse frequency x 60) / 5.5Q, = flow rate in L/hour
Serial.print (Calc, DEC); //Prints the number calculated above
Serial.print (" L/hour\r\n"); //Prints "L/hour" and returns a new line
}
void check_flow_alarm_delay ()
{
Serial.println("enter CFAD");
int Calc;
NbTopsFan = 0; //Set NbTops to 0 ready for calculations
// sei(); //Enables interrupts
Alarm.delay(1000); //Wait 1 second
// cli(); //Disable interrupts
Calc = (NbTopsFan * 60 / 5.5); //(Pulse frequency x 60) / 5.5Q, = flow rate in L/hour
Serial.print (Calc, DEC); //Prints the number calculated above
Serial.print (" L/hour\r\n"); //Prints "L/hour" and returns a new line
}
delay() uses interrupts. Disabling them interferes with the function.
What a great learning experience my first Arduino project is turning out to be.. I would now like to add a countdown until a sensor reading is taken and displayed, which will repeat infinitely. I've got the sensor and LCD display working fine but my loop is not quite right.. Should I be using a while() of some sort? How do I keep the timer ticking during the big delay between readings?
/*Code for self-watering plant with LCD readout*/
// value for LCD params
char ESC = 0xFE;
// analog input pin that the soil moisture sensor is attached to
const int analogInPin = A1;
// value read from the soil moisture sensor
int sensorValue = 0;
// if the readings from the soil sensor drop below this number, then turn on the pump
int dryValue;
// countdown timer until next soil reading
int timerValue = 9;
void setup() {
pinMode(12, OUTPUT);
// initialize serial communications at 9600 bps:
Serial.begin(9600);
// Set the "dry" value of soil on turning on the device
dryValue = analogRead(analogInPin);
// pause before intialize LCD
delay(2000);
// Initialize LCD module
Serial.write(ESC);
Serial.write(0x41);
Serial.write(ESC);
Serial.write(0x51);
// Set Contrast
Serial.write(ESC);
Serial.write(0x52);
Serial.write(40);
// Set Backlight
Serial.write(ESC);
Serial.write(0x53);
Serial.write(5);
//print the dry value to serial
Serial.print("Dry = " );
Serial.print(dryValue);
Serial.print(" ");
}
void loop(){
watering();
// wait some time (really should be delay(86400000))
delay(10000);
}
void printTimer(){
// Set cursor line 1, column 16
Serial.write(ESC);
Serial.write(0x45);
Serial.write(0x0F);
// print the timer value
Serial.print(timerValue);
timerValue = timerValue - 1;
if(timerValue == 0){
timerValue = 9;
}
}
void printVal(){
// set cursor line 2, column 1
Serial.write(ESC);
Serial.write(0x45);
Serial.write(0x40);
// print the sensor to the serial monitor:
Serial.print("Sensor = " );
Serial.print(sensorValue);
Serial.print(" ");
printTimer();
}
void watering(){
// read the analog in value:
sensorValue = analogRead(analogInPin);
//turn on the water pump for some time if the soil is too dry
if(sensorValue < dryValue){
digitalWrite(12, HIGH);
delay(2000);
digitalWrite(12, LOW);
}
else {
printVal();
}
}
It's actually really simple: Don't delay. Instead, initialize a timer to run a routine whenever it overflows or hits a certain value. Examine the datasheet for the microcontroller used in your Arduino for the specific bits to frob (note that the Arduino libraries use the timer 0 overflow vector for themselves), and the avr-libc documentation for how to denote the ISR(s) for the timer. Your loop() then becomes a big sleep while the timer runs the entire show for you.
I would use a timer library for Arduino like this http://playground.arduino.cc//Code/SimpleTimer
Just download the library, put it in the "libraries" folder in your sketchbook and restart your Arduino IDE to load the new library.
Then your code would look something like this. Basically what it does it updates the screen every loop and then once every 86400000 ms it checks the "watering" function. Just so you know this code would only check the soil once every 24 hours (86400000ms). I think a better solution would be to constantly check the soil and water anytime it is needed. But Im no gardener so maybe there is a reason for just checking once a day.
#include <SimpleTimer.h>
// the timer object
SimpleTimer timer;
void setup() {
Serial.begin(9600);
timer.setInterval(86400000, watering); // how often you would call your watering function is set with the first variable
}
void loop() {
timer.run();
printTimer();
}
void printTimer(){
// Set cursor line 1, column 16
Serial.write(ESC);
Serial.write(0x45);
Serial.write(0x0F);
// print the timer value
Serial.print(timerValue);
timerValue = timerValue - 1;
if(timerValue == 0){
timerValue = 9;
}
}
void printVal(){
// set cursor line 2, column 1
Serial.write(ESC);
Serial.write(0x45);
Serial.write(0x40);
// print the sensor to the serial monitor:
Serial.print("Sensor = " );
Serial.print(sensorValue);
Serial.print(" ");
printTimer();
}
void watering(){
// read the analog in value:
sensorValue = analogRead(analogInPin);
// send it to the display
printVal();
//turn on the water pump for some time if the soil is too dry
if(sensorValue < dryValue){
digitalWrite(12, HIGH);
delay(2000);
digitalWrite(12, LOW);
}
}