I have 2 buttons connected to 5 volts on 1 end and to D4 and D2 in stm32F401RE board. I want to drive 2 digital outputs ,D7 and D0, on some LEDs that are on series with a resistance respectively ending to ground. An extra feature was to light a board LED for a specific time which is why I have written the while scantimes part.
I have written the code but I get an error to put ; after 10 in the if statement,even after I put it, it wont fix/compile.
#include "mbed.h"
#define BLINKING_RATE 500ms
int main()
{
int scantimes = 0;
DigitalIn button1(D4);
DigitalIn button2(D2);
DigitalOut ledred(D7);
DigitalOut ledgreen(D0);
if(button1 || button2 == 1){
scantimes = 10
if(button1 == 1){
ledred == 1
}
if(button2 == 1){
ledgreen == 1
}
};
#ifdef LED2
DigitalOut led(LED2);
#else
bool led;
#endif
while (scantimes>=0) {
led = !led;
ThisThread::sleep_for(BLINKING_RATE);
}
}
Don't have "mbed.h" so can't compile, however:
in your code:
if(button1 || button2 == 1){
scantimes = 10
if(button1 == 1){
ledred == 1
}
if(button2 == 1){
ledgreen == 1
}
};
the conditional "==" operator is used in both the condition of the if statement as well as within the body of the statement.
if the goal is to "set" ledgreen or ledred to 1, use "=" instead of "==". otherwise the program is just checking whether the led's are equal to one, rather than setting their value.
Also, semicolons will be needed at the end of each statement.
Related
Need to update potentiometer values all time not only once, try different ways but nothing works :(
I think that main problem is that this function while(digitalRead(gotoPositionAPin)); blocks
Now it's read value and save speed
workflow of code
press button right save position a
press button left save position b
update pot speed (set speed)
update pot acceleration (set accel)
press button go to position A (its going with previous set of speed and acceleration)
press button go to position B (its going with previous set of speed and acceleration)
#include <AccelStepper.h>
// Define some steppers and the pins the will use
AccelStepper stepper1(1, 12, 11);
#define stepsPerRev 1600
#define stepPin 12
#define dirPin 11
#define ledPin 13
#define rotateLeftPin 7
#define rotateRightPin 6
#define savePositionAPin 5
#define savePositionBPin 4
#define gotoPositionAPin 3
#define gotoPositionBPin 2
#define maxSpeedPin 0
#define accelPin 1
// Set this to zero if you don't want debug messages printed
#define printDebug 0
// These are the constants that define the speed associated with the MaxSpeed pot
#define MAX_STEPS_PER_SECOND 1000 // At 200 s/r and 1/8th microstepping, this will be 333 rev/minute
#define MIN_STEPS_PER_SECOND 27 // At 200 steps/rev and 1/8th microstepping, this will be 1 rev/minute
// Change this value to scale the acceleration pot's scaling factor
#define ACCEL_RATIO 1
int buttonState = 0;
int stepNumber = 0;
int curSpeed = 100;
int dir = 0;
int maxSpeed = 0;
int accel = 0;
long savedPosA = 0;
long savedPosB = 0;
int loopCtr = 0;
float fMaxSpeed = 0.0;
float fStepsPerSecond = 0.0;
void setup()
{
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(ledPin, OUTPUT);
pinMode(rotateLeftPin, INPUT);
pinMode(rotateRightPin, INPUT);
pinMode(savePositionAPin, INPUT);
pinMode(savePositionBPin, INPUT);
pinMode(gotoPositionAPin, INPUT);
pinMode(gotoPositionBPin, INPUT);
if (printDebug)
{
// Initialize the Serial port
Serial.begin(9600);
}
// blink the LED:
blink(2);
stepper1.setMaxSpeed(800.0);
stepper1.setAcceleration(600.0);
// Grab both speed and accel before we start
maxSpeed = analogRead(maxSpeedPin);
// Do the math to scale the 0-1023 value (maxSpeed) to
// a range of MIN_STEPS_PER_SECOND to MAX_STEPS_PER_SECOND
fMaxSpeed = maxSpeed / 1023.0;
fStepsPerSecond = MIN_STEPS_PER_SECOND + (fMaxSpeed * (MAX_STEPS_PER_SECOND - MIN_STEPS_PER_SECOND));
if (fStepsPerSecond > 1000)
{
fStepsPerSecond = 1000;
}
accel = analogRead(accelPin)/ACCEL_RATIO;
}
void loop()
{
// First, we need to see if either rotate button is down. They always take precidence.
if(digitalRead(rotateLeftPin))
{
stepper1.setSpeed(-fStepsPerSecond);
while(digitalRead(rotateLeftPin))
{
CheckPots();
stepper1.runSpeed();
stepper1.setSpeed(-fStepsPerSecond);
}
}
else if (digitalRead(rotateRightPin))
{
stepper1.setSpeed(fStepsPerSecond);
while(digitalRead(rotateRightPin))
{
CheckPots();
stepper1.runSpeed();
stepper1.setSpeed(fStepsPerSecond);
}
}
// Go see if we need to update our analog conversions
CheckPots();
// Check to see if user is trying to save position A or B
if(digitalRead(savePositionAPin))
{
savedPosA = stepper1.currentPosition();
if (printDebug)
{
Serial.print("Saved A at :");
Serial.println(savedPosA);
}
while(digitalRead(savePositionAPin));
}
if(digitalRead(savePositionBPin))
{
savedPosB = stepper1.currentPosition();
if (printDebug)
{
Serial.print("Saved B at :");
Serial.println(savedPosB);
}
while(digitalRead(savePositionBPin));
}
// Check to see if the user wants to go to position A or B
if (digitalRead(gotoPositionAPin))
{
if (printDebug)
{
// Yup, let's go to position A
Serial.print("cur pos = ");
Serial.println(stepper1.currentPosition());
Serial.print("Going to A = ");
Serial.println(savedPosA);
Serial.print("Speed = ");
Serial.println(fStepsPerSecond);
Serial.print("Accel = ");
Serial.println(accel);
}
stepper1.setAcceleration(0);
stepper1.runToNewPosition(stepper1.currentPosition());
stepper1.setMaxSpeed(fStepsPerSecond);
stepper1.setAcceleration(accel);
stepper1.runToNewPosition(savedPosA);
if (printDebug)
{
Serial.print("new pos = ");
Serial.println(stepper1.currentPosition());
}
while(digitalRead(gotoPositionAPin));
}
else if (digitalRead(gotoPositionBPin))
{
// Yup, let's go to position B
if (printDebug)
{
Serial.print("cur pos = ");
Serial.println(stepper1.currentPosition());
Serial.print("Going to B = ");
Serial.println(savedPosB);
Serial.print("Speed = ");
Serial.println(fStepsPerSecond);
Serial.print("Accel = ");
Serial.println(accel);
}
stepper1.setAcceleration(0);
stepper1.runToNewPosition(stepper1.currentPosition());
stepper1.setMaxSpeed(fStepsPerSecond);
stepper1.setAcceleration(accel);
stepper1.runToNewPosition(savedPosB);
if (printDebug)
{
Serial.print("new pos = ");
Serial.println(stepper1.currentPosition());
}
while(digitalRead(gotoPositionBPin));
}
}
// Blink the reset LED:
void blink(int howManyTimes)
{
int i;
for (i=0; i < howManyTimes; i++)
{
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay(200);
}
}
void CheckPots(void)
{
loopCtr++;
// Only read these once in a while because they take a LONG time
if (loopCtr == 100)
{
maxSpeed = analogRead(maxSpeedPin);
// Do the math to scale the 0-1023 value (maxSpeed) to
// a range of MIN_STEPS_PER_SECOND to MAX_STEPS_PER_SECOND
fMaxSpeed = maxSpeed / 1023.0;
fStepsPerSecond = MIN_STEPS_PER_SECOND + (fMaxSpeed * (MAX_STEPS_PER_SECOND - MIN_STEPS_PER_SECOND));
if (fStepsPerSecond > 1000)
{
fStepsPerSecond = 1000;
}
}
// Read in the acceleration analog value
// This needs to be scaled too, but to what?
if (loopCtr >= 200)
{
accel = analogRead(accelPin)/ACCEL_RATIO;
loopCtr = 0;
}
}
If you're looking into "continuous operation" but don't want to introduce interrupts into your code (which will have special requirements in and of itself) there are a couple of things you need to get rid of:
Endless loops like: while(digitalRead(savePositionAPin));
System waits like: delay(200); as in your blink()
and instead use state variables. State variables are more or less what the name says: variables that hold the state of something, so you know what value the button, or timer, or counter had last time.
So, instead of a while-loop waiting for a button to be released, just set a global or static boolean that knows what state you were in the last time loop() ran, so you don't trigger the button action again. You need one boolean flag for each button.
And instead of delays, either create a state variable that holds "passed time" which you can get from millis() for example. So don't wait but instead you should just check if a certain amount of time has passed so you can toggle the state of the LED.
Adding a blinking LED to loop() - (untested example):
#define LEDWAIT 300
unsigned long myTime = 0;
bool onoff = false;
loop()
{
if (myTime == 0)
myTime = millis();
if ((millis() - myTime) > LEDWAIT) {
digitalWrite(ledPin, onoff ? HIGH : LOW);
onoff = !onoff;
myTime = millis();
}
// do other things
}
It is not entirely clear to me what your program is supposed to do and what the error is, so please correct me if I am wrong: You want to update a value based on which button is pressed? What is your opinion on using interrupts for triggering the updates?
You may want to edit the formating of your question.
I am new to coding and embedded systems and I wanted to make a button that turns off and on a LED and at the same time turn off all other futures in the system.
So far I had the button turn off and on but I cant seem to get it to also update the Potentiometer. For some reason the code would check if the button is pressed and if so then the LED would turn on and then check if the LED is on and if so then turn on the other LEDs but when I change the value of the Potentiometer( which should switch to other LEDs) it would not update and stay on the same LED. So my question is how can I put another if statement that would keep updating in the while loop?
the code that I wanted to keep updating while the first LED is on is the "else if code"
Hope that made sense.
:)
note:
I don't know if my approach is right as I am looking at the LED and not the button it self, as my code checks if the LED is on rather then if the button is pressed.
(btw its not a switch which would have made my life a lot easier :( )
#include "mbed.h"
DigitalIn userButton (PC_10);
DigitalOut led (PC_0);
bool buttonDown = false;
BusOut leds_bus (PC_1, PB_0, PA_4);
AnalogIn pot1 (PA_5);
void init_leds ();
int cntl_val = 0;
int main ()
{
cntl_val = pot1.read_u16 () / 32768;
while (true)
{
// run forever
if (userButton.read () == true)
{
// button is pressed
if (!buttonDown)
{
// a new button press
led = !led; // toogle LED
buttonDown = true; // record that the button is now down so we don't count one press lots of times
ThisThread::sleep_for (100);
}
else if (led.read () == true)
{
if (cntl_val < 1 / 3)
{
leds_bus.write (4);
}
if (cntl_val > (1 / 3) && cntl_val < (2 / 3))
{
leds_bus.write (2);
}
if (cntl_val > (2 / 3))
{
leds_bus.write (1);
}
}
}
else
{
// button isn't pressed
buttonDown = false;
}
}
}
You need to fix your math. int cntl_val is an integer so comparing it with the fractions 1/3 and 2/3 is not going to do what you expect. And cntl_val = pot1.read_u16()/32768; can set cntl_val to only 0 or 1. If the max value returned by pot.read_u16() is less than 32768 then cntl_val will only be 0.
You could maybe change cntl_val to a float but that's probably not the best option.
Instead, try setting cntl_val = pot1.read_u16(); (don't divide by 32768). And then compare cntl_val with (32768/3) and (32768*2/3). That's still ugly but better.
It is not clear from your description, but I am assuming that you have:
An on/off indicator LED
A three-LED level indicator
A momentary action button for on/off control
A potentiometer to control the input level.
And that when the system is in the "on" state you wish to indicate the potentiometer level on the level indicator? That being the case, I suggest:
Deal with button input/debounce separately from LED state determination.
Simplify the level setting; you have a level 0, 1 or 2 which you can calculate by unsigned level = (InputLevel * 3) / 32768 ;. You can then use that level value in a bit-shift (1 << level) to determine the LED to be set. Note that you had the low level set the high bit in your LED level indicator - that would require (4 >> level), which is somewhat clumsy if you were to ever increase the number of LEDs. It is easier to reverse the order of the GPIO in the BusOut object.
Additional advice:
Apply the rule of "minimal scope", localising variables to the minimum necessary scope (you have a number of unnecessary globals.
In "big-loop" scheduling, avoid thread delays during which useful work might otherwise be done. Your debounce delay unnecessarily determines the rate at which other work can be done in the loop. The advice would be different if you were polling the button and setting the LEDs in separate threads.
For example (not this is coded blind/untested - treat it as illustrative of the general principles - it may need debugging):
#include "mbed.h"
int main ()
{
static const unsigned DEBOUNCE_MS = 20u ;
static const unsigned NUMBER_OF_LEVELS = 3u ;
DigitalIn OnOffButton( PC_10 ) ;
DigitalOut OnOffLed( PC_0 ) ;
BusOut LevelIndicator( PA_4, PB_0, PC_1 ) ;
AnalogIn InputLevel( PA_5 ) ;
bool isOn = false ;
int previous_button_state = OnOffButton ;
std::uint64_t button_change_time = 0 ;
for(;;)
{
// If debounce time expired check for button state change
if( Kernel::get_ms_count() - button_change_time > DEBOUNCE_MS )
{
int current_button_state = OnOffButton ;
// If button state changed
if( current_button_state != previous_button_state )
{
// If button-down
if( current_button_state != 0 )
{
// Toggle isOn
isOn = !isOn ;
}
// Change of state and debounce update
previous_button_state = current_button_state ;
button_change_time = Kernel::get_ms_count() ;
}
}
// Set the LEDs depending on On/Off state and input level
if( isOn )
{
OnOffLed = 1 ;
// Set level indicator
LevelIndicator = 1 << (InputLevel.read_u16() * NUMBER_OF_LEVELS / 32768u) ;
}
else
{
// System inactive (Off)
LevelIndicator = 0 ;
OnOffLed = 0 ;
}
}
}
You might also consider separating out the button and indicator processing into separate functions to increase cohesion, minimise coupling, simplify testing and improve maintainability and comprehensibility.
#include "mbed.h"
void updateIndicators( bool isOn ) ;
bool getOnOffState() ;
int main ()
{
for(;;)
{
updateIndicators( getOnOffState() ) ;
}
}
bool getOnOffState()
{
static const unsigned DEBOUNCE_MS = 20u ;
static DigitalIn OnOffButton( PC_10 ) ;
static bool state = false ;
static int previous_button_state = OnOffButton ;
static std::uint64_t button_change_time = 0 ;
// If debounce time expired check for button state change
if( Kernel::get_ms_count() - button_change_time > DEBOUNCE_MS )
{
int current_button_state = OnOffButton ;
// If button state changed
if( current_button_state != previous_button_state )
{
// If button-down
if( current_button_state != 0 )
{
// Toggle isOn
state = !state ;
}
// Change of state and debounce update
previous_button_state = current_button_state ;
button_change_time = Kernel::get_ms_count() ;
}
}
return state ;
}
void updateIndicators( bool isOn )
{
static const unsigned NUMBER_OF_LEVELS = 3u ;
static DigitalOut OnOffLed( PC_0 ) ;
static BusOut LevelIndicator( PA_4, PB_0, PC_1 ) ;
static AnalogIn InputLevel( PA_5 ) ;
// Set the LEDs depending on On/Off state and input level
if( isOn )
{
OnOffLed = 1 ;
// Set level indicator
LevelIndicator = 1 << (InputLevel.read_u16() * NUMBER_OF_LEVELS / 32768u) ;
}
else
{
// System inactive (Off)
LevelIndicator = 0 ;
OnOffLed = 0 ;
}
}
I already have my code to work, I'm just trying to make it look nicer now. Just to give a really short summary on what my device does: Smart parking system that detects cars going in and out of a parking lot and displays how many vacant spots are available or not at the entrance. Right now the output looks like this:
Vacant Spots: 1
Vacant Spots: 1
Vacant Spots: 1
Vacant Spots: 1
Vacant Spots: 0
.
.
.
.
.
This is in the case of when a car is entering so it's decrementing by 1 and it increments when a car leaves since there's a added vacant spot available. What I'm trying to do is have the output look like this:
"
Vacant Spots: 1
"
The only thing I want to change is the numerical value. I don't want a continuous stream of
" Vacant Spots: 1 "s to show at the LCD display for the parking user to see. Is there a way to just clear the serial monitor after the loop ends without having it output a new value below it continuously? I've provided the code for the program. I have 3 xbees (1 coordinator and 2 routers). The two routers dont have code on them and are just sending data to the coordinator. The coordinator is where it receives the data. This is the code for the coordinator:
int readValue = 0;
void setup()
{
Serial.begin(9600);
}
int vslots = 1;
void loop()
{
if(Serial.available()>21)
{
if(Serial.read() == 0x7E)
{
for(int i=0;i<19;i++)
{
byte discard = Serial.read(); //Next 18 bytes, it's discarded
}
readValue = Serial.read();
bool flagTrue = false;
bool flagFalse = false;
if((readValue == 0) && flagTrue == false ) //EXIT
{
flagTrue = true;
flagFalse = false;
Serial.print("Vacant Spots: ");
Serial.println(vslots);
}
else if((readValue == 16 && flagFalse == false) && vslots >= 1)
//DECREMENT (CAR ENTERING)
{
flagTrue = false;
flagFalse = true;
vslots -= 1;
Serial.print("Vacant Spots: ");
Serial.println(vslots);
}
if((readValue == 18) && flagTrue == false )
{
flagTrue = true;
flagFalse = false;
Serial.print("Vacant Spots: ");
Serial.println(vslots);
}
else if((readValue == 19 && flagFalse == false) && vslots <= 10)
//INCREMENT (CAR EXITING)
{
flagTrue = false;
flagFalse = true;
vslots += 1;
Serial.print("Vacant Spots: ");
Serial.println(vslots);
}
}
}
}
First, you need to understand that Arduino serial terminal is not like a real terminal software It does not support a command sent on UART. So to achieve what you want you will require real terminal software such as putty. Which allows you to make changes by sending character bytes using UART communication.
//ADD these lines before printing on a serial terminal
Serial.write(27); // 27 is an ESC command for terminal
Serial.print("[2J"); // this will clear screen
Serial.write(27); // 27 is an ESC command for terminal
Serial.print("[H"); // move cursor to home
//now print what you want...
Serial.print("Vacant Spots: ");
Serial.println(vslots);
For more info and methods you can check this post here. But had tried everything and suggesting to go with putty.
The ln suffix in println stands for new line. That means println will "print" the value and a newline.
So as an initial solution you could change from using println to plain print:
Serial.print("Vacant Spots: ");
Serial.print(vslots); // Note: not println
Then we have to solve the problem of going back to the beginning of the line. to overwrite the old text. This is typically done with the carriate-return character '\r'. If we add it to the beginning of the printout:
Serial.print("\rVacant Spots: "); // Note initial cariage-return
Serial.print(vslots); // Note: not println
Then each printout should go back to the beginning of the line, and overwrite the previous content on that line.
To make sure that each line is equally long, you could use e.g. sprintf to format the string first, and then write it to the serial port:
char buffer[32];
// - for left justification,
// 5 for width of value (padded with spaces)
sprintf(buffer, "\rVacant Spots: %-5d", vslots);
Serial.print(buffer);
I'm new to coding and C++.
The code below is meant to monitor a magswitch and a status led on another controller. The code needs to run once the magswitch pin goes high (this works).
The additional code for pulseIn, is what I hope to use to monitor different flash rates of the led when I get the code working. For now I'm just looking for the state variable to update with the if and else if statements.
When I toggle the statusPin, the code picks up the changing state, but I cannot get it to update the "state" and "statuspinstate" variables.
The statuspinstate variable shows as 1, even though it is initialized as 0.
I inserted all the serial prints to try and see where things are going wrong.
This is the serial print when "statusPin" is LOW:
statuspinstate: 0
rate1: 2147483647
period: 0.00
rate2: 0
ontime: 0
offtime: 0
state: 0
statepinstatus: 1
This is the serial print when "statusPin" is HIGH
statuspinstate: 1
rate1: 2147483647
period: 0.00
rate2: 0
ontime: 0
offtime: 0
state: 0
statepinstatus: 1
Code:
const int statusPin = 19; //Reads status led
const int magSwitch = 22; //Magswitch to detect movement
int ontime,offtime,rate1,rate2;
float freq,period;
volatile unsigned int state =0;
volatile unsigned int statuspinstate = 0;
void setup()
{
pinMode(statusPin, INPUT); //input from controller
pinMode(magSwitch, INPUT);
Serial.begin(115200);
}
void loop()
{
while (digitalRead(magSwitch) == LOW) {
}
{
statuspinstate = digitalRead(statusPin);
ontime = pulseIn(statusPin,HIGH);
offtime = pulseIn(statusPin,LOW);
period = ontime+offtime;
rate1 = (ontime/period); //future use
rate2 = (offtime); //future use
Serial.println(String("statuspinstate ") + (digitalRead(statusPin))); //all serial print is debug info
Serial.println(String("rate1: ") + (rate1));
Serial.println(String("period: ") + (period));
Serial.println(String("rate2: ") + (rate2));
Serial.println(String("ontime: ") + (ontime));
Serial.println(String("offtime: ") + (offtime));
delay(500);
}
if ((ontime) != 0)
state = period;
else if (statuspinstate = 1)
state = 9999;
else if (statuspinstate = 0);
state = 0;
Serial.println(String("state: ") + (state));
Serial.println(String("statepinstatus: ") + (statuspinstate));
statuspinstate = 0; //return statuspinstate to zero
}
Look at your conditional, with proper indentation (do get a text editor that can indent your code for you):
if ((ontime) != 0)
state = period;
else if (statuspinstate = 1)
state = 9999;
else if (statuspinstate = 0);
state = 0;
We know that ontime is zero, so the second condition is tried next.
Now, statuspinstate = 1 is an assignment, not a comparison, and its value is "truth-y" so you take that branch.
Next, the stray semicolon in if (statuspinstate = 0); (which is also an assignment condition, but not evaluated) makes state = 0 unconditional.
So every time ontime is zero, you end up executing statuspinstate = 1 and state = 0.
What you probably want is
if (ontime != 0)
state = period;
else if (statuspinstate == 1)
state = 9999;
else if (statuspinstate == 0)
state = 0;
I'm trying to turn a light "On" and "Off" with Arduino using a Relay, Photo-resistor and Serial Communication. The problem come in to play when I try to turn the light Off when the Photo-resistor is receiving a low value and has received an instruction via Serial Communication to prevent the "IF" statement from activating, it simply doesn't not work as the light is kept on.
I'm using 4 "IF" statement to control the light: auto light using Photo-resistor and serial value resumed in "ON/OFF", turn light on using serial value "h", turn light off using serial value "l" and another serial value to control the auto light statement using "a" to control the first statement.
How can I use a value to control light based on a sensor and serial output at the same time. In other words, how can I stop light from turning on automatically?? What I'm doing wrong or what I left?
Here is my simple code:
char val;
boolean setAuto=true; // Automatic Light Status Value
int ldr;
int relayPin=4;
void setup() {
pinMode(relayPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
ldr = analogRead(A0); // Read value from Photoresistor
if ( Serial.available()) {
val = Serial.read(); // Get serial value
}
if ( setAuto == true && ldr < 50 ) { // Here is the main problem
digitalWrite(relayPin, HIGH);
}
else if ( val == 'h' ) {
digitalWrite(relayPin, HIGH); // Work
}
else if ( val == 'l') {
digitalWrite(relayPin, LOW); // Work
}
else if (val == 'a') { // Here is the other part of the problem
setAuto = !setAuto; // Changing value for automatic light
}
}
The first if statement:
if ( setAuto == true && ldr < 50 ) { // Here is the main problem
digitalWrite(relayPin, HIGH);
} else {
takes precedence over the next two if statements. Since setAuto is ALWAYS true and so when ldr < 50 the light thru relayPin is ON.
Think about how you might want to setAuto to false.
Hint. You might want to evaluate val just after it is read:
if ( Serial.available()) {
val = Serial.read(); // Get serial value
if (val == ..... logic to affect the course of events.....
}