Move mouse cursor with delays constantly and click when analog value above 300. Arduino Pro Micro - arduino

I am using Pro Micro as a USB Host and moving the cursor to predefined positions on the screen with a delay of 5 seconds. I'm using the AbsMouse library for absolute mouse cursor positions. What I want is, when the analog input goes above 300, I want it to perform XYZ function. Because I'm using delays of 5000, I can't poll the analog input always.
Basically, I want the cursor to move to these absolute positions continuously in a loop. Whenever the analog value goes above 300, it should perform the press and release functions.
I am not able to understand how to use Elapsed millis() or interrupts. Please show exactly how can it be done in code.
Help Much appreciated.
#include <AbsMouse.h>
int sensorValue = 0;
void setup()
{
AbsMouse.init(1920, 1080);
}
void loop()
{
sensorValue = analogRead(A0);
AbsMouse.move(640, 127);
delay(5000);
AbsMouse.move(640, 400);
delay(5000);
AbsMouse.move(640, 625);
delay(5000);
AbsMouse.move(1280, 127);
delay(5000);
AbsMouse.move(1280, 400);
delay(5000);
AbsMouse.move(1280, 625);
delay(5000);
if (sensorValue >= 300)
{
AbsMouse.press(MOUSE_LEFT);
AbsMouse.release(MOUSE_LEFT);
}
}

Implementing a delay of 5 seconds measuring elapsed milliseconds and reading the analog value while waiting goes like this:
startTime = millis();
while(millis()-startTime < 5000) {
sensorValue = analogRead(A0);
if (sensorValue >= 300) {
AbsMouse.press(MOUSE_LEFT);
AbsMouse.release(MOUSE_LEFT);
}
}
This has two disadvantages that you'll have to solve if needed. The first one is that the click events will be performed while the value stays above 300 (i.e. it can click more than once). The second problem, is that this is not an exact delay of 5 seconds, as it can have a jitter due to the code being executed inside the while block.
Another option, as you mentioned, is to use timer interrupts to achieve a more exact delay. Using a library like TimerOne it goes like this (inspired from library examples and modified to execute every 5 seconds):
#include <TimerOne.h>
void setup(void) {
Timer1.initialize(5000000);
Timer1.attachInterrupt(fiveSeconds);
}
void fiveSeconds(void) {
// do stuff
}
The function fiveSeconds should be executed every 5 seconds, with more precision than the millis() approach.
Now you should add code to that function, to achieve what you want to do. I'd suggest to use loop() for reading the analog value and clicking, and the interrupt for moving the mouse cursor, but your approach might be different.

Related

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.

Arduino Interrupt getting triggered more than once - Working with Hall Sensor for RPM

I am working with an hall sensor for counting the RPM of my wheel. I am using following sensor :
My code as follows :
int hall_pin = 3; // digital pin
float hall_threshold = 5.0;
float count = 0;
void setup() {
pinMode(hall_pin,INPUT);// put your setup code here, to run once:
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(hall_pin),hall_ISR,RISING);
}
void loop() {
count = 0.0;
float start = micros();
while(1){
if(count >= hall_threshold){
break;
}
}
float end_time = micros();
float time_passed = (end_time - start)/1000000.0; // in seconds
float rpm = (count/time_passed)*60.0;
Serial.println(rpm);
delay(10000);
}
void hall_ISR()
{
count+=1.0;
}
I am using digital pin 3 to read from sensor and count the number of times it detects magnetic field using interrupt. Since the sensor outputs 1 on detecting, I have used a RISING interrupt. Once the count is greater than 5 then the control comes out of the infinite loop and calculates the RPM. The problem is this interrupt is getting triggered multiple times. I have tried using detachInterrupt(hall_pin) but it is not working. I also tried to decrease the sensitivity of hall sensor using the trimmer provided.
I am sure the problem is not with the sensor, it is with the interrupt, I guess. Where am I going wrong?
Any help is very much appreciated!
Thank you.

How to constantly listen for button input in Arduino?

I am trying to create a working physical simulation of a traffic light intersection. I want to listen for button readings (pedestrian buttons to turn pedestrian lights green) continuously throughout the program and want to run a different function that will handle pedestrian lights if the buttons are ever pressed during the program.
I have tried it with while loops and if conditions but it just won't work because then it would read the button input at a specific point in time when I want it to read the readings constantly throughout the program and break the loop if the condition is ever untrue (while and do-while loops only check the condition at the end of the loop when I want it to check the condition throughout the loop). I also need to get which button was pressed if that possible. Then depending on which button was pressed, I want to run a function called pedes() or pedes2().
Feel free to ask if you need any clarifications.
I have posted my original code below that I want to run constantly until a button will be pressed.
Thanks!
// If at any point in time during this code, a button is pushed, I want to run a function called
pedes() or pedes2() depending on which button is pressed.
// First set of Trafiic Lights
int redT = 13 ;
int yellowT = 12;
int greenT = 11;
// First set of Pedestrian Lights
int redP = 10;
int greenP = 9;
// Second set of Traffic Lights
int redT2 = 8;
int yellowT2 = 7;
int greenT2 = 6;
// Second set of Pedestrian Lights
int redP2 = 5;
int greenP2 = 4;
// Pedestrian Buttons
int buttonT = 3;
int buttonT2 = 2;
int buttonT3 = 1;
int buttonT4 = 0;
int buttonStateT = 0;
int buttonStateT2 = 0;
int buttonStateT3 = 0;
int buttonStateT4 = 0;
// Booleans which will handle which button was pressed
void setup() {
// First set of Trafiic Lights
pinMode(redT, OUTPUT);
pinMode(yellowT, OUTPUT);
pinMode(greenT, OUTPUT);
// First set of Pedestrian Lights
pinMode(redP, OUTPUT);
pinMode(greenP, OUTPUT);
// Second set of Traffic Lights
pinMode(redT2, OUTPUT);
pinMode(yellowT2, OUTPUT);
pinMode(greenT2, OUTPUT);
// Second set of Pedestrian Lights
pinMode(redP2, OUTPUT);
pinMode(greenP2, OUTPUT);
// Pedestrian Buttons
pinMode(buttonT, INPUT);
pinMode(buttonT2, INPUT);
pinMode(buttonT3, INPUT);
pinMode(buttonP4, INPUT);
}
void loop() {
// Resetting all the traffic lights
digitalWrite(redP, HIGH); // Turns on red pedestrian LED from 1st bunch
digitalWrite(redP2, HIGH); // Turns on red pedestrian LED from 2nd bunch
digitalWrite(yellowT, LOW); // Turns off yellow traffic LED from 1st bunch
digitalWrite(yellowT2, LOW); // Turns off yellow traffic LED from 1st bunch
digitalWrite(redT, HIGH); // Turns on red traffic LED from 1st bunch
digitalWrite(redT2, HIGH); // Turns on red traffic LED from 2nd bunch
delay(2000);
digitalWrite(redT, LOW); // Turns off red traffic LED from 1st bunch
digitalWrite(redT2, HIGH); // Turns on red traffic LED from 2nd bunch
digitalWrite(greenT, HIGH); // Turns on green traffic LED from 1st bunch
digitalWrite(greenT2, LOW); // Turns off green traffic LED from 2nd bunch
delay(10000); // Pauses program for 8 seconds
digitalWrite(greenT, LOW); // Turns off green traffic LED from 1st bunch
digitalWrite(yellowT, HIGH); // Turns on yellow traffic LED from 1st bunch
delay(3000); // Pauses program for 3 seconds
digitalWrite(yellowT, LOW); // Turns off yellow traffic LED from 1st bunch
digitalWrite(redT, HIGH); // Turns on red traffic LED from 1st bunch
delay(2000); // Pauses program for 3 seconds
digitalWrite(redT2, LOW); // Turns off red traffic LED from 2nd bunch
digitalWrite(greenT2, HIGH); // Turns on green traffic LED from 2nd bunch
delay(6000); // Pauses program for 8 seconds
digitalWrite(greenT2, LOW); // Turns off green traffic LED from 2nd bunch
digitalWrite(yellowT2, HIGH); // Turns on yellow traffic LED from 2nd bunch
delay(3000); // Pauses program for 3 seconds
digitalWrite(yellowT2, LOW); // Turns off yellow traffic LED from 2nd bunch
digitalWrite(redT2, HIGH); // Turns on red traffic LED from 2nd bunch
delay(2000); // Pauses program for 3 seconds
}
Instead of constantly polling you could use an interrupt on the button pin and set a flag or call a function from within the interrupt routine.
Also make sure to debounce the button in hardware or software.
Since you seem to be learning, here are some extra improvements you could add as an exercise:
To switch the lights you could use timer interrupts instead of delays (you could even put the mcu in sleep mode in between).
Another improvement would be to create a TrafficLight class which contains all the logic. Here is an interesting tutorial. This way you could easily create multiple objects: TrafficLight tl1(..), tl2(..); or even arrays of traffic lights (for example with the same timings).
You could then even create a class Intersection which contains all the traffic lights and the logic for that intersection.
Well if you delay for 10 seconds you cannot react to something in the meantime.
You can use millis() to implement a non-blocking delay.
https://www.arduino.cc/en/tutorial/BlinkWithoutDelay
Instead of being idle and unable to respond you spend your time with checking and responding to your button states and/or time conditions.
Avoid using delays. Delays will pause everything until the time is up, which makes everything less responsive. Delays are useful when learning how to code, but they can hinder usability if you need to react to an external sensor or button.
A better habit to get into is using timers instead of delays. This lets your code keep looping without pausing, and you can add code to check for user input more frequently.
Here is an example of what you should NOT do:
void loop() {
digitalWrite(MY_LED,HIGH);
delay(1000);
digitalWrite(MY_LED,LOW);
delay(1000);
//This code only gets reached every 2 seconds
//This means you may need to hold the button for up to
//2 seconds before it will print a message
if (digitalRead(MY_BUTTON) == LOW) {
Serial.println("You pressed the button");
}
}
You can use millis() to return the number of milliseconds since the arduino started running. Here is a basic example of a timer:
bool ledState = false;
unsigned long toggledTime = 0; //The last time we toggled the led
void loop() {
//Calculate how much time has passed since the last time
//we turned the LED on or off
unsigned long timeElapsedSinceLastToggle = millis() - toggledTime;
//If 1000ms (1s) has passed, we'll toggle the LED
if (timeElapsedSinceLastToggle > 1000) {
ledState = !ledState; //Invert the state
digitalWrite(MY_LED,ledState); //Perform the action
toggledTime = millis(); //Reset our timer to the current time
}
//This code now checks very frequently since the code above
//never uses delay()
if (digitalRead(MY_BUTTON) == LOW) {
Serial.println("You pressed the button");
}
}
I would recommend using a different timer for each LED that you want to toggle. This will make your code much more responsive, and your buttons will respond (nearly) instantly.
There is one thing you will want to be careful with regarding timers. millis() is how many milliseconds since boot, but what happens when your code runs for a very long time? millis() resets (starts over at 0) after about 50 days. For lots of people, this doesn't matter much, but it is worth keeping in mind if your code will be running indefinitely for long periods of time.

Repeat blink sketch for a specified time

I need help with an Arduino sketch , I want to repeat the blink sketch for a specified amount of time (3minutes for example) , then Stop .As we know , the loop() keeps runing forever which is not what I want . Any ideas how I can achieve this , blinking an LED for X minutes and Stopping ?
You should probably make use of some timer library. A simple (maybe naive) way to achieve what you want to do is to make use of a boolean that is set to 0 when 3 minutes has passed or simply digitalWrite the led to low when the timer has passed.
Check this link:
http://playground.arduino.cc/Code/Timer
I suggest that you use int after(long duration, callback).
Below is a (very) simple example of how you probably could do:
#include "Timer.h"
Timer t;
LED = 1;
void setup() {
int afterTime = t.after(180000, cancelLED);
}
void loop() {
t.update();
if(LED) {
//The "write HIGH" statement in your sketch here.
}
else {
//Write the led to LOW
}
}
void cancelLED() {
LED = 0;
}
I haven't used the library myself, I just checked the the docs and wrote an example to give you some ideas. Don't expect it to work right away.

How to get a fixed number of delays through arduino in a stepper motor?

I have to stop the stepper motor certain number of times (for one complete rotation) with delays as the stopping parameters.Suppose my requirement is to stop the motor 20 number of times so that my delay value should be evenly distributed between this number (20) for complete one rotation.I used a for loop for these stops(20) but i get delys more than 20.My code for arduino is given below where 8000 are the number of steps in one revolution:
#include <Stepper.h>
const int stepsPerRevolution = 200; // change this to fit the number of steps per revolution
// for your motor
// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);
void setup() {
// set the speed at 60 rpm:
myStepper.setSpeed(60);
// initialize the serial port:
Serial.begin(9600);
}
// step one revolution in one direction:
void loop() {
int noi=20;// set the no of images here
for(int i=0;i<=noi;i++){
delay(8000/noi);
}
Serial.println("clockwise");
myStepper.step(stepsPerRevolution);
}
Your question is still confusing, but more clear than before.
It looks like you have a stepper motor that drives a turntable. The motor takes 200 steps for one revolution, but it takes 8000 steps to turn the turntable one revolution.
In one sense, all that matters is the number 8000. To make the table pause, you need to divide 8000 into equal pieces, as it looks like you attempted. But you have misplaced a }.
void loop() {
int noi=20;// set the no of images here
for(int i=0;i<=noi;i++){
delay(8000/noi);
} <<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE
Serial.println("clockwise");
myStepper.step(stepsPerRevolution);
}
void loop() {
int noi=20;// set the no of images here
for(int i=0;i<=noi;i++){
delay(enough_delay_to_take_image); // or trigger image here?
Serial.println("clockwise");
myStepper.step(8000/noi);
}
}
The only place that stepsPerRevolution = 200 matters is in calculating the speed of the movement, along with myStepper.setSpeed(60);. Do you really wanting the table to move that quickly? It might cause the object to shake too much.
myStepper.setSpeed(1);
will cause the movements betyween images to take 3 seconds. If that is too slow,
myStepper.setSpeed(3);
will cause the movements betyween images to take 1 second.

Resources