Make my arduino accomplish task at specific time - arduino

I'm a newbie to arduino. What I need is make him do something at specific time, and go to sleep, so that it doesn't work excessively.
Specific task is: I want him to start a mechanism for feeding my gold fish, so in vacation time arduino should work for 10 days or more (this is reason for sleep mode).
When researching this problem, I came up with time interrupts, but I don't think this is best solution, because I want him do something at specific time, not to to interrupt his task.
Thank you for any kind of help :)

I've read that the standard Arduino board doesn't save that much power, as the power regulator and USB port (if present) draws significant power. But given that you use an external clock to trigger the device to wakeup, there's a simple arduino library, Enerlib, that you can use.
Engblaze has a nice article on how to do it yourself, but if you're new to the arduino, you might not want to jump into AVR libraries.

you can try something easy like every 30 seconds starts an event of 20 seconds of duration :
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;
void setup () {
Serial.begin(57600);
#ifdef AVR
Wire.begin();
#else
Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
#endif
rtc.begin();
if (! rtc.isrunning()) {
Serial.println("RTC is NOT running!");
}
}
boolean pumpOn = false;
void loop () {
DateTime now = rtc.now();
if(now.second()%30==0){ pumpOn=true;}
if(now.second()%50==0){ pumpOn=false;}
if(pumpOn)
Serial.println("on");
}
}

Use the millis() method. It will reset after 50 days but I don't think you will be traveling for so long...
unsigned long hours4nextFeeding = 8;
unsigned long lastTime = millis();
void loop() {
if(millis() > (lastTime + (hours4nextFeeding*3600*1000))) {
feedTheFish();
lastTime = millis();
}
delay(60000);
}
Also you can use a light sensor (supercheaper) and feed the fish once a day when the sun rises
The code I just wrote is untested but you should get the idea.

I like #Josh's solution of using the clock to reset the device, but here's another idea if your fish will die if they aren't fed on the millisecond.

Related

ARDUINO UNO- Need explains about program

I am begginer on Arduino. I am student and this is my first homework.
Please, could someone explain to me how to understand the following codes. Which code is better? How do operators affect the executive speed? Below is the content.
"The task was to measure the speed of code execution depending on the programming technique used. The program code was designed to expose the high and low states to the D10 (PB2) port respectively without entering delays – as a result, we obtained a rectangular waveform with the maximum frequency for a given program recording method. Programs were written by putting all statements in void setup() omitting the void loop().
Preparation for the exercise consisted in connecting the Arduino Uno board to the USB port, starting the Arduino IDE environment and turning on the oscilloscope. The oscilloscope was used to observe the rectangular waveform generated from the D10 pin (PB2) and to measure its frequency."
Code of the first program:
const byte outPin = 10;
void setup() {
pinMode(outPin,OUTPUT);
while (1)
{
digitalWrite(outPin, HIGH);
digitalWrite(outPin, LOW);
}
Code of the second program:
const byte outPin = B00000100;
void setup() {
DDRB | = outPin;
while (1)
{
PORTB = B00000100;
PORTB = B11111011;
}
Third program code:
const byte outPin =10;
byte state =0;
void setup() {
pinMode(outPin,OUTPUT);
while (1)
{
digitalWrite(outPin, state);
state = !state;
}
Code of the fourth program:
#define _BV(n) (1<<n)
const byte outPin= B00000100;
byte state = _BV(2);
void setup()
{
DDRB|=outPin;
}
while (1){
PORTB |=state;
PORTB &=~state;
}
Code of the fifth program:
const byte outPin= B00000100;
void setup()
{
DDRB|=outPin;
while (1){
PORTB |=B00000100;
PORTB &=B11111011;}
}
As I said I am begginer on ARDUINO UNO. I cannot find any solution to explain exactly my homework.
Which code is better?
The first one, of course. Reasons:
Usually, it's fast enough.
The other ones are hardware specific and do not run on any Arduino, but just on atmega328P microcontrollers.
How do operators affect the executive speed?
It's the call to digitalWrite, which makes the difference, not some operators like ~ . You should look for an similarly hardware independent replacement to digitalWrite, which does the translation between Arduino pin number and hardware register only once at compile time.
BTW: your question is off topic here :)

Arduino timer not counting accuratly

I am working on a school project for which I rotate a servo after a cable disconnects and a specific delay is over. This is my current code. We are using an Arduino Uno powered from the USB port
#include <Servo.h>
int reader=4;
int servo1Pin=8;
Servo servo1;
int value;
int pos=10;
int wacht=5000;
void setup() {
pinMode(reader, INPUT);
servo1.attach(servo1Pin);
}
void loop() {
value = digitalRead(reader);
servo1.write(pos);
if (value == LOW) {
delay(wacht);
pos=180;
}
else {
pos=10;
}
}
wacht is the specific delay. When we disconnected pin 4 to break that circuit we don't have a consistent time between the interruption of the power flow and the opening of the servo. It seems to vary from anywhere between 5 to 40 seconds of delay after triggering. Does anyone have any ideas to solve this issue?
try change
pinMode(reader, INPUT);
to
pinMode(reader, INPUT_PULLUP);
And for clarification delay don't use timer.
The order of your instructions seem strange. the usual order is:
Read
Decide
Act
Also, you may want to avoid sending useless instructions to the servo. For example, when you know the servo is already in the correct position. You should not rely on eternal code to do the right thing. In other terms, you have no idea how long servo1.write() takes to execute.
Which would give for your loop()
void loop()
{
if (digitalRead(reader) == LOW)
{
if (pos != 180)
{
delay(wacht); // delay() is only called once, when circuit breaks.
// this guarantees immediate response when circuit
∕/ closes again.
pos = 180;
servo1.write(pos);
}
}
else if (pos != 10)
{
pos = 10;
servo1.write(pos);
}
}
Also, have a look and implement Peter Plesník's answer. This will probably solve some of your problems. You input will definitely still have a random lag of up to 5 seconds when closing the circuit, though.

my serial port did not show my sensor data properly

Hey i got a bit problem with my Arduino and sensor
Here is what i tried ;
#define USE_ARDUINO_INTERRUPTS true // Set-up low-level interrupts for most acurate BPM math.
#include <PulseSensorPlayground.h> // Includes the PulseSensorPlayground Library.
#include <SoftwareSerial.h>
SoftwareSerial blue(0,1);
const int PulseWire = 0; // PulseSensor PURPLE WIRE connected to ANALOG PIN 0
const int LED13 = 13; // The on-board Arduino LED, close to PIN 13.
int Threshold = 550;
PulseSensorPlayground pulseSensor;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
blue.begin(9600);
pulseSensor.analogInput(PulseWire);
pulseSensor.blinkOnPulse(LED13); //auto-magically blink Arduino's LED with heartbeat.
pulseSensor.setThreshold(Threshold);
pulseSensor.begin();
}
void loop() {
// put your main code here, to run repeatedly:
int myBPM = pulseSensor.getBeatsPerMinute();
if(myBPM>200){
myBPM-100;
}
if (pulseSensor.sawStartOfBeat()) {
Serial.println(myBPM);
blue.println(myBPM);
}
delay(10);
}
this code I got from the example library and modified it.
so i want to send data to my android using Bluetooth but this sensor kinda ticked me off because whenever i use it with my HC-06 Bluetooth module it suddenly got a hearth beat without i even touching it and it just sends so much data ignoring the delay I set.
I just need to slowly sending data just like a second but the data didn't show up
so anyone can help?
I read your code and I noticed this piece of code
if(myBPM > 200){ myBPM - 100; }
that is poorly written if (I understand correctly) you want to check the size of myBPM and if it is larger than 200 then it should be subtracted 100.
it should be:
myBPM = myBPM - 100; not myBPM - 100;
I hope my answer will help you. Have a nice day!

Why does delay() cause my arduino to reset?

I am using an Arduino Uno, connected to a USB shield, a RFID shield(adafruit PN532), an LCD, EEPROM(24AA256) and a RTC module(DS1307). I will not post my code here because it is too large and it is separated in multiple files.
In my program, I realize that if my programs enters a certain functions, after entering function after function, if I use a delay() at the end of the function I am currently in, the arduino resets. An example of what I mean is below.
void a() { b(); }
void b() { c(); }
void c() { d(); }
void d()
{
lcd_string("Testing", 0x80);
delay(2000); <---- Arduino resets at the delay here
}
At first, I thought it was because my dynamic memory was at 80%, and when I compiled, they said the Arduino might have some stability issues. So I modified my code such that my dynamic memory is now 57%. Problem still exist.
I thought maybe the delay() function has some overflow or something, so I tried replacing the delay with the following code.
unsigned long timing;
timing = millis();
timing += 2000;
while(millis() < timing);
The Arduino still resets.
Next, I thought maybe because my arduino is connected to my PC, some serial pin might have been causing the reset, so I used an external Power to power up the arduino and disconnected the USB. The arduino still resets.
Next, I thought maybe Timer1 might have been crashing with the delay() function, although the delay function uses Timer0 so I disabled my Timer1 . The arduino still resets.
Is there any other possibilities that I am missing out? My program storage space is at 69% which I believe shouldn't be an issue.
Edit
Here is my code for Timer1 ISR
ISR(TIMER1_OVF_vect)
{
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 34286;// = (16*10^6) / (1*1024) - 1 (must be <65536)
TCCR1B |= (1 << CS12);
// enable timer compare interrupt
TIMSK1 |= (1 << TOIE1);
triggered = 1;
}
Any other interrupt of flags used are in the library header files.
I am using the following external libraries
USB Host shield library 2.0
Adafruit PN532 master
A little sample to come close to RAM corruption ...
#define MEM_PER_LEVEL 50
#define TRY_TO_SURVIVE 10
void KillMe(int level) {
byte dummy[MEM_PER_LEVEL];
for ( byte i = 0; i < MEM_PER_LEVEL; i++)
dummy[i]= i;
Serial.println(level);
delay(1000); // not sure why this would hurt more than others
if (level < TRY_TO_SURVIVE) KillMe(level+1);
for ( byte i = 0; i < MEM_PER_LEVEL; i++) {
if (dummy[i] != i) {
Serial.println(F("corruption happened"));
while(1) {} // HALT
}
}
if (level == 0)
Serial.println(F("survived"));
}
void setup() {
Serial.begin(9600);
KillMe(0);
}
void loop() { }
I had the same problem - wherever I put a delay in my setup function the Arduino would restart.
For me, the problem was an instance of SoftwareSerial with invalid pin numbers.
SoftwareSerial mySerial(30, 31);
Anyone else landing on this question should check their pin numbers are appropriate for the board they're targeting. Not sure why the crash only happens if a delay is called, would be interested if anyone has insight into this!

Are interrupts the right thing to use for my robot?

So I have this old motorized wheelchair that I am trying to convert into a robot. I replaced the original motor driver with a sabertooth 2x12 and I’m using an Arduino micro to talk to it. The motors shaft goes all the way threw so I attached a magnet and a Hall Effect sensor to the back side to act as a rotary encoder. My current goal is to be able to tell the robot to move forward a certain amount of feet then stop. I wrote some code to do this linearly however this didn't work so well. Then I learned about interrupts and that sounded like exactly what I needed. So I tried my hand at that and things went wrong on several different levels.
LEVEL ONE: I have never seemed to be able to properly drive the motors it seems like any time I put the command to turn them on inside of a loop or if statement they decide to do what they want and move sporadically and unpredictably
LEVEL TWO: I feel like the interrupts are interrupting themselves and the thing I set in place to stop the wheels from moving forward because I can tell it to move 14 rotary encoder clicks forward and one wheel will continue moving way past 1000 clicks while the other stops
LEVEL THREE: couple times I guess I placed my interrupts wrong because when I uploaded the code windows would stop recognizing the Arduino and my driver would break until I uploaded the blink sketch after pressing the reset button which also reloaded and fixed my drivers. Then if I deleted one of my interrupts it would upload normally.
LEVEL FOUR: my Hall Effect sensors seem to not work right when the motors are on. They tend to jump from 1 to 200 clicks in a matter of seconds. This in turn floods my serial port and crashes the Arduino ide.
So as you can see there are several flaws somewhere in the system whether it’s hardware or software I don't know. Am I approaching this the right way or is there some Arduino secret I don’t know about that would make my life easier? If I am approaching this right could you take a look at my code below and see what I’m doing wrong.
#include <Servo.h>//the motor driver uses this library
Servo LEFT, RIGHT;//left wheel right wheel
int RclickNum=0;//used for the rotory encoder
int LclickNum=0;//these are the number of "clicks" each wheel has moved
int D =115;//Drive
int R =70;//Reverse
int B =90;//Break
int Linterrupt = 1;//these are the interrupt numbers. 0 = pin 3 and 1 = pin 2
int Rinterrupt = 0;
int clickConvert = 7;// how many rotery encoder clicks equal a foot
void setup()
{
Serial.begin(9600); //starting serial communication
LEFT.attach( 9, 1000, 2000);//attaching the motor controller that is acting like a servo
RIGHT.attach(10, 1000, 2000);
attachInterrupt(Linterrupt, LclickCounter, FALLING);//attaching the rotory encoders as interrupts that will
attachInterrupt(Rinterrupt, RclickCounter, FALLING);//trip when the encoder pins go from high to low
}
void loop()
{//This is for controling the robot using the standard wasd format
int input= Serial.read();
if(input == 'a')
left(2);
if(input == 'd')
right(2);
if(input == 'w')
forward(2);
if(input == 's')
backward(2);
if(input == 'e')
STOP();
}
void forward(int feet)//this is called when w is sent threw the serial port and is where i am testing all of my code.
{
interrupts(); //turn on the interrupts
while(RclickNum < feet * clickConvert || LclickNum < feet * clickConvert)// while either the left or right wheel hasnt made it to the desired distance
{
if(RclickNum < feet * clickConvert)//check if the right wheel has gone the distance
RIGHT.write(D); //make the right wheel move
else
RIGHT.write(B);//stop the right wheel
if(LclickNum < feet * clickConvert)
LEFT.write(D);
else
LEFT.write(B);
}
noInterrupts();//stop the interrupts
resetCount();//set the click counters back to zero
}
//once i have the forward function working i will implament it through out the other functions
//----------------------------------------------------------------------
void backward(int feet)
{
RIGHT.write(R);
LEFT.write(R);
}
void left(int feet)
{
RIGHT.write(D);
LEFT.write(R);
}
void right(int feet)
{
RIGHT.write(R);
LEFT.write(D);
}
void STOP()
{
resetCount();
RIGHT.write(B);
LEFT.write(B);
}
void LclickCounter()//this is called by the left encoder interrupt
{
LclickNum++;
Serial.print("L");
Serial.println(LclickNum);
}
void RclickCounter()//this is called by the right encoder interrupt
{
RclickNum++;
M Serial.print("R");
Serial.println(RclickNum);
}
void resetCount()
{
RclickNum=0;
LclickNum=0;
}
don't use interrupt() and nointerrupt() (or cli() and sei()) as they will stop timer and serial interrupt, breaking a lot of things. Just set to 0 the counting variable OR use detachInterrupt and attachInterrupt.
variable used inside interrupt AND normal execution flow should be declared as volatile, or their value my be unsyncornized. So declare them like volatile int RclickNum=0;
interrupt should be fast to execute, as by default other interrupt will NOT execute while inside an interrupt.
NEVER use Serial inside interrupt; if Serial buffer is full, it will call Serial.flush(), that will wait for Serial interrupt of byte written, but because you are alreadi inside an interrupt will never happen...dead lock aka you code hangs forever!
because your "moving" function use quite a long time to execute, if multiple command arrive to the serial, thay will remain isnode the buffer until readed. So if in the terminal you write "asd" and then "e", you will see robot go left, backward, right, stop (yes, actually the stop function is not usefull as it does nothing because your "moving" function are "blocking", that mean they won't return until they ended, so the loop() code (and the read of "e") will not execute until the buffer of serial has been processed.

Resources