how to use arduino uno millis function() - arduino

I wrote a program for Arduino UNO with attached Funshield, which will animate the following pattern on the four vertical LEDs.At any given moment, exactly one LED (of four) is turned on (we are starting with the topmost one). In each step of the animation, the active LED moves one slot down. When it hits the bottom, it bounces and moves upwards again, until it reaches top. The animation repeats itself forever.
One step of the animation takes exactly 300ms
#include <funshield.h>
int ledPin[] = {led1_pin, led2_pin, led3_pin, led4_pin};
void setup() {
for (int i = 0; i<5; i++)
pinMode(ledPin[i], OUTPUT);
}
void loop() {
int i = 0;
for (i = 5-1; i>=0; i--)
digitalWrite(ledPin[i], LOW);
delay(1000);
digitalWrite(ledPin[i], HIGH);
for (i; i<5; i++) {
digitalWrite(ledPin[i], LOW);
delay(500);
digitalWrite(ledPin[i], HIGH);
}
}
if i using the delay() function, it works perfectly,but when i used millis() function , 4 LEDs light up at the same time.I would like to know what is causing the animation to stall.
#include "funshield.h"
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 300;
const byte liu = 4;
int ledPin[] = { led1_pin, led2_pin, led3_pin, led4_pin };
void setup() {
for (int i = 0; i < 5; i++)
pinMode(ledPin[i], OUTPUT);
startMillis = millis();
}
void loop()
{
currentMillis = millis();
if (currentMillis - startMillis >= period)
int i = 0;
for (int i = 0; i > 4; i++) {
digitalWrite(liu, !digitalRead(liu));
digitalWrite(ledPin[i], LOW);
digitalWrite(ledPin[i], HIGH);
startMillis = currentMillis;
}
for (int i = 4; i >= 0; i--) {
digitalWrite(liu, !digitalRead(liu));
digitalWrite(ledPin[i], LOW);
digitalWrite(ledPin[i], HIGH);
startMillis = currentMillis;
}
}

first of all unsigned long nowTime; should be at the top, outside of your loop
secondly, you need to use nowTime = millis(); for the specific time that you want to record the current time (this should be before you use the (millis()-nowtime>300)
and lastly, remove (unsigned long)
from this line
if(unsigned long)(millis()-nowtime>300)
for further clarification on how to use millis, read this article on arduino's official website

Related

Servo keeps jittering Arduino code for servo motor jittering

Servo keeps jittering at start up, buttons only reset to initial position being held, if let goes back to jittering.
There is a line of code as well for an osciloscope but im not using it if you can please point it out, also this is the original website and functioning, the tinkercad simulation works like intended, but on my arduino keeps jittering https://www.tinkercad.com/things/3jdNc6hhgZl-arduino-servo-wo-servo-lib
Edit: I've checked that on the simulation it also jitters..
const unsigned int _PERIOD_US = 2200;
const unsigned int _0_DEG_US = 500;
const unsigned int _90_DEG_US = 1500;
const unsigned int _180_DEG_US = 2500;
unsigned int us_elapsed = 0;
unsigned int duty_us = _90_DEG_US;
unsigned int aux = 0;
void setup()
{
pinMode(8, OUTPUT);
pinMode(4, INPUT);
pinMode(3, INPUT);
pinMode(2, INPUT);
digitalWrite(8, LOW);
}
void loop()
{
if (digitalRead(4) == LOW) {
duty_us = _0_DEG_US;
}
if (digitalRead(3) == LOW) {
duty_us = _90_DEG_US;
}
if (digitalRead(2) == LOW) {
duty_us = _180_DEG_US;
}
aux = micros() - us_elapsed;
if (aux >= duty_us) {
digitalWrite(8, LOW);
}
if (aux >= _PERIOD_US) {
digitalWrite(8, HIGH);
us_elapsed = micros();
}
}

Using a Arduino Mega instead of a Uno for a capacitive sensor

I was trying to use a Arduino Mega to substitute a Arduino Uno. The folliwing code works fine in Uno but doesn't work on Mega (I already changed the ports to it). It is used for a Capacitive touchsensor:
#define resolution 8
#define mains 60 // 60: north america, japan; 50: most other places
#define refresh 2 * 1000000 / mains
void setup() {
Serial.begin(9600);
// unused pins are fairly insignificant,
// but pulled low to reduce unknown variables
for(int i = 2; i < 14; i++) {
pinMode(i, OUTPUT);
digitalWrite(i, LOW);
}
for(int i =22; i < 53; i++){
pinMode(i, OUTPUT);
digitalWrite(i, LOW);
}
pinMode(8, INPUT);
startTimer();
}
void loop() {
Serial.println(time(8, B00100000), DEC);
}
long time(int pin, byte mask) {
unsigned long count = 0, total = 0;
while(checkTimer() < refresh) {
// pinMode is about 6 times slower than assigning
// DDRB directly, but that pause is important
pinMode(pin, OUTPUT);
PORTH = 0;
pinMode(pin, INPUT);
while((PINH & mask) == 0)
count++;
total++;
}
startTimer();
return (count << resolution) / total;
}
extern volatile unsigned long timer0_overflow_count;
void startTimer() {
timer0_overflow_count = 0;
TCNT0 = 0;
}
unsigned long checkTimer() {
return ((timer0_overflow_count << 8) + TCNT0) << 2;
}
I would like to know what I need to change on the Timer interrupt stuff to make it work properly.

How to convert delay to millis

I have a simple code with delays.
I'd like to know how to convert this code to millis? Is there a function to do so?
long revers = 1000;
void setup() {
pinMode(D1, OUTPUT);
pinMode(D2, OUTPUT);
}
void loop() {
digitalWrite(D1, LOW);
delay(revers);
digitalWrite(D2, HIGH);
delay(revers);
digitalWrite(D2, LOW);
delay(revers);
digitalWrite(D1, HIGH);
delay(revers);
}
The basic concept is this: record the millis() at a given moment in a variable - say 'starttime'. Now, during every loop(), check the time that has elapsed by subtracting millis() from 'starttime'. If the elapsed time is greater than the delaytime you set, execute code. Reset the starttime to create a repeating pattern.
That may be too short of an explanation for you, so before you dive into the code, I highly advise you to read this introduction about using millis() for timing. It's lengthy, but it explains the principle extensively. This will help you understand the code below.
Lastly, there are several libraries written to make the use of timing easier. For instance the SimpleTimer-library, but you can google "arduino timer library" for others. I've included an example below.
1 second on, 3 seconds off:
unsigned long startMillis; //some global variables available anywhere in the program
unsigned long currentMillis;
const unsigned long period = 1000; //the value is a number of milliseconds
int fase; //value used to determine what action to perform
void setup() {
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
startMillis = millis(); //initial start time
fase = 0;
}
void loop() {
currentMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)
if (currentMillis - startMillis >= period) //test whether the period has elapsed
{
if (fase == 0)
{
digitalWrite(8, LOW);
startMillis = currentMillis; //IMPORTANT to save the start time of the current LED state.
fase = 1; //increment fase, so next action will be different
}
else if (fase == 1)
{
digitalWrite(7, HIGH);
startMillis = currentMillis;
fase = 2;
}
else if (fase == 2)
{
digitalWrite(7, LOW);
startMillis = currentMillis;
fase = 3;
}
else if (fase == 3)
{
digitalWrite(8, HIGH);
fase = 0;
startMillis = currentMillis;
}
}
}
Example of a flashing led using the SimpleTimer library
#include <SimpleTimer.h>
// the timer object
SimpleTimer timer;
int ledPin = 13;
// a function to be executed periodically
void repeatMe() {
digitalWrite(ledPin, !digitalRead(ledPin));
}
void setup() {
pinMode(ledPin, OUTPUT);
timer.setInterval(1000, repeatMe);
}
void loop() {
timer.run();
}

How to add a time delay when reading a sensor - arduino

I am making a project that has to sense ambient light with a LDR. The idea is, that when the value of the LDR is low for 3 seconds, the led turns on. Also when the value of that LDR gets higher again, and stays high for 3 seconds, the led should turn of. This is so I can avoid that just a cloud or somebody waving over the sensor turns the led on immediately.
I know that I can use the mills() function here like in the blink without delay tutorial. But it doesn't seem to work....
this is my code so far:
#define ledPin 2
#define ldrPin A0
int daylight = 430;
int night = 150;
int ledState = 0;
int lightState = 0;
const long timeOut = 2000;
unsigned long previousMillis = 0;
unsigned long previousMillis2 = 0;
unsigned long tNow = 0;
void setup() {
// put your setup code here, to run once:
pinMode(ledPin, OUTPUT);
pinMode(ldrPin, INPUT);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
tNow = millis();
int value = analogRead(ldrPin);
switch (lightState) {
case 0:
ledState = 0;
if (value <= 200 && (tNow - previousMillis) >= timeOut)
{
previousMillis = tNow;
lightState = 1;
}
break;
case 1:
ledState = 1;
if (value >= 300 && (tNow - previousMillis2) >= timeOut)
{
previousMillis2 = tNow;
lightState = 0;
}
break;
}
switch (ledState) {
case 0:
digitalWrite(ledPin, LOW);
break;
case 1:
digitalWrite(ledPin, HIGH);
break;
}
Serial.println(value);
Serial.println(ledState);
}
You could try using smoothing to read a running average from the sensor. That way you'll have a smoothed average instead of an immediate value, so a short spike (like a hand) won't change the value if you keep the window long enough.
There is a tutorial on the arduino website explaining how to do this. Basically you store multiple previous values and keep track of the average.

How can I set a ceratin time interval for reading input in my Arduino game?

I'm making a game with my Arduino Uno.
4 leds on the breadboards are displaying a random binary number.
The player needs to press the button to put in the number that he sees
(for example, if the leds are 0011, push the button 3 times).
If he guessed right, he wins (another led blinks). If not, he loses (led turns on and stays on).
But I want the player to automatically lose if he hasn't pressed a button for two seconds.
But I'm really a beginner so bear with me. Below I'll post what I've got so far. But it's not exactly working. When I turn it on, without me pressing the button, it just goes straight to "you win" and the next round. What am I doing wrong?
int led1 = 9;
int led2 = 6;
int led3 = 5;
int led4 = 3;
int ledResult = 13; //will blink when you won, stay on when you lost
int buttonPin = 2;
int val = 0; // variable for reading the pin status
int buttonPushCounter = 0;
int buttonState = 0;
int lastButtonState = 0;
long interval = 2000;
long randomNumber;
void setup() {
Serial.begin(9600); //starts serial communication
pinMode (led1, OUTPUT);
pinMode (led2, OUTPUT);
pinMode (led3, OUTPUT);
pinMode (led4, OUTPUT);
pinMode (ledResult, OUTPUT);
pinMode (buttonPin, INPUT);
randomSeed(analogRead(A0)); //the pin is unconnected so it'll return something random (0-1023)
}
void loop() {
randomNumber = random(1, 16);
Serial.println("Random Numbers sequence"); //just for self-check
Serial.println(randomNumber);
if (randomNumber >= 8)
{
digitalWrite (led1, HIGH);
randomNumber - 8;
}
else
{
digitalWrite (led1, LOW);
}
if (randomNumber >= 4)
{
digitalWrite (led2, HIGH);
randomNumber - 4;
}
else
{
digitalWrite (led3, LOW);
}
if (randomNumber >= 2)
{
digitalWrite (led4, HIGH);
randomNumber - 2;
}
else
{
digitalWrite (led1, LOW);
}
if (randomNumber = 1)
{
digitalWrite (led2, HIGH);
}
else
{
digitalWrite (led1, LOW);
}
unsigned long currentMillis = millis();
if (currentMillis > interval) {
Serial.println("You lost.");
digitalWrite(ledResult, HIGH);
}else{
//READ BUTTON STATE
buttonState = digitalRead(buttonPin);
// compare the buttonState to its previous state
if (buttonState != lastButtonState) {
if (buttonState == HIGH)
{
buttonPushCounter++;
Serial.println("Button push counter:");
Serial.println(buttonPushCounter);
}
// Delay a little bit to avoid bouncing
delay(50);
}
// save the current state as the last state, for next time through the loop
lastButtonState = buttonState;
if (buttonPushCounter = randomNumber) {
Serial.println("You won!");
digitalWrite(ledResult, HIGH);
delay(700);
digitalWrite(ledResult, LOW);
delay(700);
}
else
{
Serial.println("You lost.");
digitalWrite(ledResult, HIGH);
}
}
}
Essentially you'll want to have a main loop that probes/polls for user input, and if there's no input from the user on probe, then check the current millis time against when you called it for start. This will give you the elapsed time since no input was detected. If the elapsed time is greater than your threshold, you break out of the loop and check a timeout flag to see if you proceed with the button validation code or branch to the "lose" code.
Without writing the whole thing, here's a C pseudo-code mock up of the idea (commented to explain):
void loop() {
while (is_running) { // main loop
unsigned long start = millis(); // get starting probe time
bool timeout = false;
while ((buttonState = probe_input()) == no_input_val) {
/* probe_input function returned no input,
so check for timeout. If the probe_input function
did return a 'value', then this loop won't iterate
and you can check the buttonState below */
if ((millis() - start) >= interval) {
/* millis is monotonic time, so calling it, then
subtracting the value from the start value will give
us elapsed time since user did not give input. */
timeout = true;
break;
}
}
if (!timeout) {
/* button state/level code */
} else {
// lose code
}
}
}
Again, this is just pseudo-code and won't compile as you'd need to implement the probe_input function to poll for input, but it's more to illustrate what you'd need to do to get you moving in the direction you're wanting.
I hope that can help.

Resources