So far I have wrote code so that if 1 then enter pressed or send clicked, and then 1 again and enter pressed or send clicked causes LED one to turn on, if ‘1’ ‘0’ is entered in a similar way then LED 1 turns off, and so on for LEDs two and three, ie: ‘2’ ‘1’ turns on LED 2, ‘3’ ’0’ turns off LED 3.
int incomingVal;
int ledPin = 16;
int ledPin2 = 15;
int ledPin3 = 14;
void setup()
{
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
Serial.println("starting");
pinMode(ledPin,OUTPUT);
pinMode(ledPin2,OUTPUT);
pinMode(ledPin3,OUTPUT);
}
void loop()
{
if (Serial.available() > 0 ) //then chars are in the serial buffer
{
incomingVal = Serial.parseInt();
Serial.print("You entered: ");
Serial.println(incomingVal);
if (incomingVal == 10)//turns off led 1
{
digitalWrite(ledPin, LOW);
}
if (incomingVal == 11)//turns on led 1
{
digitalWrite(ledPin, HIGH);
}
if (incomingVal == 20)//turns off led 2
{
digitalWrite(ledPin2, LOW);
}
if (incomingVal == 21)//turns on led 2
{
digitalWrite(ledPin2, HIGH);
}
if (incomingVal == 30)//turns off led 3
{
digitalWrite(ledPin3, LOW);
}
if (incomingVal == 31)//turns on led 3
{
digitalWrite(ledPin3, HIGH);
}
}
}
How could i change the code so i can enter a third value to change the brightness from 0 to 250? For example, typing “2,1,125” would make LED 2 to light up at 50% brightness.
To make the LED light up at half brightness you need to use pulse width modulation. Make sure that the pins you are using have ~ next to them (pins 3, 5, 6, 9, 10, 11 on the Uno).
I would change your input method slightly, because 0 brightness is essentially the same as turning the LED off, you should only need 2 numbers. The first number corresponds to the LED, the second number corresponds to the brightness.
int led_pins[3] = {9,10,11};
int incomingVal;
int brightness;
int parsed_value;
int x = 0;
void setup()
{
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
Serial.println("starting");
pinMode(led_pins[0],OUTPUT); // You could also use a loop here
pinMode(led_pins[1],OUTPUT);
pinMode(led_pins[2],OUTPUT);
}
void loop()
{
if (Serial.available() > 0 ) //then chars are in the serial buffer
{
incomingVal = Serial.parseInt();
Serial.print("You entered: ");
Serial.println(incomingVal);
//figure out which LED we selected
parsed_value = incomingVal;
while (parsed_value > 9){
/*
because of integer division, this line will remove the last
number from the integer. ie 11 / 10 = 1 (the result is rounded down)
The loop will continue until only 1 digit remains
*/
x++;
parsed_value = parsed_value / 10;
}
// x represents the number of times parsed_value was divided by 10
// this line removes the first digit of the incoming value, leaving
// the brightness
brightness = incomingVal - pow(10,x)*parsed_value;
/*parsed_value will be 1 greater than the array key value because
the array is 0 based.*/
//set the LED to the right brightness
analogWrite(led_pins[parsed_value-1],brightness);
}
}
Related
I have connected coin hopper and coin acceptor to one arduino uno, coin acceptor connected to pin 2, coin hopper to pin 3 - sensor and pin 7 - relay. When coin hopper switch relay, it is executing coininterrupt
for coin hopper I am using this script link
coin acceptor script: link
I need this 2 scripts working on 1 arduino
my code:
#define SENSOR 3
#define RELAY 7
#define ACCEPTOR 2
volatile boolean insert = false;
int pulse=0,count;
char sen;
int temp=0;
unsigned long int timer;
void setup()
{
Serial.begin(9600);
pinMode(SENSOR,INPUT_PULLUP);
pinMode(RELAY,OUTPUT);
sen=digitalRead(SENSOR);
digitalWrite(RELAY, HIGH);
attachInterrupt(digitalPinToInterrupt(ACCEPTOR), coinInterrupt, RISING);
}
void loop()
{
if (insert) {
insert = false;
Serial.println("coin");
delay(1000);
}
if(Serial.available())
{
timer=millis();
// temp is amount to dispense send to arduino
temp=Serial.parseInt();
if(temp>0){
digitalWrite(RELAY,LOW);}
}
sen=(sen<<1)|digitalRead(SENSOR);
// if hopper sensor read drop coin
if(sen==1)
{
timer=millis();
pulse++;
sen&=0x03;
Serial.println("out 1");
//if dispensed coins equal with coins to dispense stop engine
if(pulse==temp)
{
digitalWrite(RELAY,HIGH);
pulse=0;
temp=0;
}
}
// if amount dispensed is not equal with amount to dispense and engine running, stop
if((digitalRead(RELAY)==LOW)&(millis()-timer>2000))
{
digitalWrite(RELAY,HIGH);
pulse=0;
temp=0;
}
}
void coinInterrupt() {
insert = true;
}
I was trying to change pins (arduino uno support interrupts on pin 2 and 3 only) but problem still appears so I guess there is issue in the code
your sketch does not run in this state :
first fix errors :
declare insert as volatile
remove cpulse (not used anywhere)
change 'if()' to (I suppose) 'if (insert) ....'
remove stuff with 'sen' var : simply use if(digitalRead(SENSOR)) or if(!digitalRead(SENSOR))
except if you need to store relay state.
use logical operators like || or && unless you really need bitwise operations
example of result sketch :
#define SENSOR 3
#define RELAY 7
volatile boolean insert = false;
byte amountToDispense = 0;
int pulse = 0;
int temp = 0;
unsigned long int timer;
void setup()
{
Serial.begin(9600);
pinMode(SENSOR, INPUT_PULLUP);
pinMode(RELAY, OUTPUT);
digitalWrite(RELAY, HIGH);
attachInterrupt(digitalPinToInterrupt(2), coinInterrupt, RISING);
}
void loop()
{
if (insert ) {
insert = false;
Serial.println("coin");
delay(1000);
}
if (Serial.available())
{
timer = millis();
temp = Serial.parseInt();
if (temp > 0) {
//amountToDispense = Serial.read() - 48;
digitalWrite(RELAY, LOW);
}
}
if (digitalRead(SENSOR))
{
timer = millis();
pulse++;
Serial.println("out 1");
if (pulse >= temp)
{
digitalWrite(RELAY, HIGH);
pulse = 0;
temp = 0;
}
}
if (!digitalRead(RELAY) && (millis() - timer > 2000))
{
digitalWrite(RELAY, HIGH);
pulse = 0;
temp = 0;
}
}
void coinInterrupt() {
insert = true;
}
What is this supposed to do?
sen=(sen<<1)|digitalRead(SENSOR);
You init sen with digitalRead(SENSOR);
Assuming that pin is LOW when you start the sketch and turns HIGH, sen will become 1.
Next you do sen &= 0x03 so sen is still 1.
Again sen=(sen<<1)|digitalRead(SENSOR); , sen will either be 2 or 3.
Next loop run sen=(sen<<1)|digitalRead(SENSOR); sen is now 4 or 6. and so on...
I don't have time to think about what you want to achieve but this is definitely a problem as you'll only enter if (sen == 1) once and never again.
If this is not sufficient you should probably improve your post as it is unclear what arduino sends bad signal to interrup pin is supposed to mean. That doesn't make sense. Explain the expected behaviour of your program and how it behaves instead. add more comments so it becomes clear what you intend to do with each block of code so we don't have to interpret
So, I have my program here, I am trying to make a program that, we manually pull the wire out and place it back, each time I pull it out, it is 1 iteration and placing it back in is 1 iteration. Whenever it is connected to the port the external LED is dark, when it is pulled out, the external LED is bright. I should be able to do this for 10 iterations and stop once I get there.
The problem is, when I include the while(true); statement in, my external LED does not work, but without the statement in there, the program runs the way I want except that it does not stop working after 10 iterations, any help is appreciated!
#include<EEPROM.h>
const int LED = 12;
const int SWITCH = 4;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(LED, OUTPUT); //LED is always outputting information
pinMode(LED_BUILTIN, OUTPUT); //Built in LED is always outputting information
pinMode(SWITCH, INPUT_PULLUP); //Switch inputs value when in/out of ground
}
void loop() {
// put your main code here, to run repeatedly:
int addr = 0; //Declaring variables
int count = 0;
int seconds;
if (digitalRead(SWITCH) == LOW) { //If wire starts in ground, record values
Serial.println("----Recording----");
while (count <= 10) { //While count value is less than or equal to 10
if (digitalRead(SWITCH) == LOW) { //When wire is connected to 4
count = count + 1; //Add one to count in each iteration
digitalWrite(LED, LOW); //LED light is off in this position
delay(50); //Checks switch state every 0.05 seconds
}
else if (digitalRead(SWITCH) == HIGH) { //When wire isnt connected to 4
count = count + 1; //Add one to count in each iteration
digitalWrite(LED, HIGH); //LED light is on in this position
delay(50); //Checks switch state every 0.05 seconds
}
while (true);
}
}
}
Why it's not working? Let's rewrite your code a little:
while (count <= 10) {
count = count + 1;
digitalWrite(LED, digitalRead(SWITCH));
delay(50);
while (true); // aaand kill it
}
I'm ommiting the race condition if the first digital read returns HIGH and then the second returns LOW (it wouldn't wait for 50ms to stop)
I'd expect something like counting on pin change or so:
while (count <= 10) {
byte = digitalRead(SWITCH);
if (byte != digitalRead(LED))
{
count = count + 1;
digitalWrite(LED, byte);
}
delay(50);
}
while (true); // aaand kill it
I have a rotary encoder and a DC gear motor connected to my Arduino UNO. I would like to rotate the DC motor at a certain angle. As I right now, I have written a code that reads the position of my encoder as I rotate it and prints out the position and the angle. I have also written code that runs the dc motor at fixed amount of time.
I would like to rotate the dc motor at a certain angle. For example, if I input 90 degrees my motor should rotate 90 degrees and stop.
I'm using pin 2 and pin 3 for my channel A and B (ENCODER)
I'm using pin 9 to control my dc motor.
I have no clue how to approach this... any thoughts?
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int lcd_case = 0;
volatile int timeToRun = 0;
int motorPin = 6;
#define BTN_RIGHT 0
#define BTN_LEFT 1
#define BTN_UP 2
#define BTN_DOWN 3
#define BTN_SELECT 4
#define BTN_NONE 5
#define SELECT 6
#define RESET 7
#define PIN
#define encoderPinA 2
#define encoderPinB 3
#define CPR 256
volatile int counter =0;
volatile boolean flag;
volatile int var_degrees =0;
void setup() {
pinMode(3, OUTPUT);
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
Serial.begin (9600);
attachInterrupt(digitalPinToInterrupt(encoderPinA), isr_2, RISING);
lcd.clear();
}
void loop() {
if(flag == true){
var_degrees = ((360/256.0)*counter);
Serial.println(var_degrees);
//lcd.setCursor(0, 1);
//lcd.print("Degrees: ");
//lcd.setCursor(9, 1);
//lcd.print(var_degrees);
flag = false;
}
lcd_case = readButtons();
int read_button = analogRead (0);
//Depending on which button we pressed, we performan action
switch (lcd_case) {
case BTN_RIGHT:
{
break;
}
case BTN_LEFT:
{
break;
}
case BTN_UP:
{
timeToRun = timeToRun +1;
lcd.setCursor(0, 1);
lcd.print("Degrees: ");
lcd.setCursor(9, 1);
lcd.print(timeToRun);
delay(500);
break;
}
case BTN_DOWN:
{
if (timeToRun > 0) {
timeToRun = timeToRun - 1;
lcd.setCursor(0, 1);
lcd.print("Degrees: ");
lcd.setCursor(9, 1);
lcd.print(timeToRun);
delay(500);
break;
}
}
case BTN_SELECT:
{
analogWrite(motorPin, 255);
// I NEED TO ROTATE MOTOR BASED ON ANGLE IN ENCODER
delay(timeToRun * 100); //ONLY ROTATES DC MOTOR IN SECONDS
break;
}
case RESET:
{
break;
}
}
}
//Interrupts
void isr_2(){
flag = true;
if(digitalRead(encoderPinA) == HIGH){
if(digitalRead(encoderPinB) == LOW){
counter = counter -1; //COUNTER CLOCK WISE
}
else{
counter = counter +1; //CLOCK WISE
}
}
else{ //IF PIN A IS LOW
if(digitalRead(encoderPinB) == LOW){
counter = counter +1; //CLOCK WISE
}
else{
counter = counter -1 ; //COUNTER CLOCK WISE
}
}
}
int readButtons() {
int read_button;
read_button = analogRead (0);
if (read_button < 50) {
return BTN_RIGHT;
}
if (read_button < 195) {
return BTN_UP;
}
if (read_button < 400) {
return BTN_DOWN;
}
if (read_button < 600) {
return BTN_LEFT;
}
if (read_button < 800) {
return BTN_SELECT;
}
else
return BTN_NONE;
}
It's good that you are correctly reading the position of the armature of your motor. Now is the time to use PID and closed loop! Tuned PID is a controller that helps your motor to go to the desired position at the best possible time with the lowest possible overshoot(error) It takes a control course to learn all of this. You will basically need a feedback loop that takes the "desired angle", give it to the controller which moves the motor. Then you get the current position of the motor, which will be fed back to the origin of the system. Your "desired angle" minus "current angle" will be how much your motor should move each time the micro controller go over the loop.
Here is how the feedback loop looks like:
And here is link to learn control. Good luck!
Control Tutorials
Edit 2: I should probably give you an intro on what PID is as well. PID controller is made of three different components:
Proportional
Integral
Derivative
Each time you get your "Desired Angle" - "Actual Angle" or "e" as shown in diagram, you will times it by Kp. Find its derivative with respect to previous e and times it by Kd, and find the integral of the errors and times it by Ki. You can start by ignoring Ki and integral, and add it if it was needed later. After you got Kpe+Kdd(e)/dt, this values is the percentage of power you will output to your motor. Kp and Kd and Ki is where the real engineering comes into play. You should find them using the transfer function of your system and fine-tune them in MatLab or a similar software. These values are usually low (less than 1). It really depends on your system. For my motor, they were Kp=0.001 and Kd=0.02
I am just creating a simple basic program, but I can't figure out what's going wrong.
I have set three pins as output and three pins as input. When those three pins digitalRead == HIGH they will set an LED to HIGH, but instead my LED is always staying high.
Here is my Arduino code:
int LED_Low = 4; // Red LED
int LED_Avg = 3; // Yellow LED
int LED_High = 2; // Green Led
int WaterLow = 7;
int WaterAvg = 8;
int WaterHigh = 9;
void setup() {
// Put your setup code here, to run once:
pinMode(LED_Low, OUTPUT);
pinMode(LED_Avg, OUTPUT);
pinMode(LED_High, OUTPUT);
pinMode(WaterLow, INPUT);
pinMode(WaterAvg, INPUT);
pinMode(WaterHigh, INPUT);
}
void check(){
if(digitalRead(WaterLow) == HIGH){ // If Water level is low
digitalWrite(ledLow, HIGH); // Turn on red LED indication water level is low
}
else{
digitalWrite(ledLow, LOW);
}
if(digitalRead(WaterAvg) == HIGH){ // If water level is medium
digitalWrite(ledAvg, HIGH); // Turn on yellow LED indicating water level is average
}
else{
digitalWrite(ledAvg, LOW);
}
if(digitalRead(WaterHigh) == HIGH){ //
digitalWrite(ledHigh, HIGH); //
}
else{
digitalWrite(ledHigh, LOW);
}
}
void loop() {
// Put your main code here, to run repeatedly:
check();
}
In the above image I have connected led on pin 2, 3, and 4 with 1.5 kilohm resistor and three wires in pin 7, 8, and 9 which will receive input from the 5 volt pin and turn on the LED. Accordingly, the 5 volt pin is connected to the positive terminal on the power bus and with 9.1 *2 resistors in series and then this wire connect with pin 2, 3, and 4.
I found the issue. My code was OK. It was my circuit.
The pins I declared to receive input were not connected to ground.
You can make that with the help of two cases
Define the delay
if (digitalRead(WaterLow) == HIGH) // If Water level is low
{
digitalWrite(ledLow, HIGH); // Turn red LED indication water level is low
delay(2000);
}
else
{
digitalWrite(ledLow, LOW);
}
Make a condition like this
int stateled = LOW;
int previous = LOW;
long time = 0;
long debounce = 200;
void loop()
{
stateButton = digitalRead(WaterLow);
if (stateButton == HIGH && previous == LOW && millis() - time > debounce)
{
if(stateLED == HIGH)
{
stateLED = LOW;
}
else
{
stateLED = HIGH;
}
time = millis();
}
digitalWrite(ledlow, stateLED);
previous == stateButton;
}
I am trying to write a program that will do the following :
Write code so that if 1 then enter pressed or send clicked, and then 1 again and enter pressed or send clicked causes LED one to turn on, if ‘1’ ‘0’ is entered in a similar way then LED 1 turns off, and so on for LEDs two and three, ie: ‘2’ ‘1’ turns on LED 2, ‘3’ ’0’ turns off LED 3.
So far here is my code:
int incomingVal;
int ledPin = 16;
int ledPin2 = 15;
int ledPin3 = 14;
void setup()
{
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
Serial.println("starting");
pinMode(ledPin,OUTPUT);
pinMode(ledPin2,OUTPUT);
pinMode(ledPin3,OUTPUT);
}
void checkForRecvdChar ();
void loop()
{
if (Serial.available() > 0 ) //then chars are in the serial buffer
{
incomingVal = Serial.parseInt();
Serial.print("You entered: ");
Serial.println(incomingVal);
if (incomingVal == 10);//turns off led 1
{
digitalWrite(ledPin, LOW);
}
if (incomingVal == 11);//turns on led 1
{
digitalWrite(ledPin, HIGH);
}
if (incomingVal == 20);//turns off led 2
{
digitalWrite(ledPin2, LOW);
}
if (incomingVal == 21);//turns on led 2
{
digitalWrite(ledPin2, HIGH);
}
if (incomingVal == 30);//turns off led 3
{
digitalWrite(ledPin3, LOW);
}
if (incomingVal == 31);//turns on led 3
{
digitalWrite(ledPin3, HIGH);
}
}
}
Right now it turns all LEDs on no matter what combination I enter
you've got semi colons after your if statements, which terminates the if statement. So all your intended if blocks get executed.
for example...
if (incomingVal == 31);//turns on led 3
{
digitalWrite(ledPin3, HIGH);
}
needs to be
if (incomingVal == 31)
{
digitalWrite(ledPin3, HIGH);
}
Ok So First It Will Better To Use Switch Case in this Case:
1. You Can Just Use The Same Number To Turn The Led ON and OFF
Example:
case 1:
{
if(wFlag == false)
{
digitalWrite(LED, HIGH);
wFlag = true;
Serial.println("LED is ON");
}
else if (wFlag == true)
{
digitalWrite(LED, LOW);
wFlag = false;
Serial.println("LED is OFF");
}
break;
}
2. The Way You Do It, Your Problem Is Serial Read Gets Only Byte after Byte
So When You Press 1 or 11 It Sees 1 Because It is The First one "1" and Then Do Your If
Statment.
You Can Fix it Like This:
while (Serial.available())
{
IncomingData = Serial.parseInt();
Temp += String(IncomingData); //Temp String Var
}
DataIN = Temp.toInt(); //DataIN int Var
Temp =""; // Rest The Temp String
Switch(DataIN) // Or if(DataIN == 1)
{
}