I am trying to write the code for an embedded board (RX63N)in which I want to use the LCD along with the on board switches for the following functionality:
On pressing the switch the program should "pause" or "unpause" depending on the previous state and the LCD should display "paused" when it is paused. On unpausing, the LCD should display the custom graphics at the position defined by x and y. It is displayed using the function Set_LCD_Char(N) where N is defined as a custom graphic from a bitmap image. But I will need to clear the LCD before making any changes and that is where I am struggling. On using lcd_clear() function anywhere in the while keeps the LCD blank (or almost blank i.e. the text and graphics are so faint that they are as good as absent) Can someone please help me? heres the code:
while (1)
{
// lcd_clear();
if(g_sw3_press == true){ //detect switch press
pause_flag = !pause_flag;
g_sw3_press = false; //reset switch
}
if (pause_flag){
RESET_ALL_LEDS();
jet_x = 0;
jet_y = 0;
Set_Font_Bitmap(); //changes from text mode to bitmap
Set_LCD_Pos(jet_x,jet_y);
Set_LCD_Char(3);
}
else if(!(pause_flag)){
ALL_RED_LEDS_ON();
Set_Font_8_by_8();
lcd_display(LCD_LINE1, " PAUSED ");
}
}
Firstly, it's generally not a good idea to do a busy polling loop as you are doing. But I can't recommend any concrete alternatives as platform and OS (if any) have not been provided (perhaps your platform has no support for events).
Anyway, not sure if this is the answer you need. But since you ask for an example and I can't effectively put code into the comments, below is what I mean. The problem is that you are continuously writing and clearing the LCD. So in effect the two operations are competing with each other. So one way to solve this is to only update the LCD when the state changes.
while (1)
{
if(g_sw3_press == true){ //detect switch press
pause_flag = !pause_flag;
g_sw3_press = false; //reset switch
} else {
/* No state change - nothing to do. Poll again. */
continue;
}
lcd_clear();
if (pause_flag){
RESET_ALL_LEDS();
jet_x = 0;
jet_y = 0;
Set_Font_Bitmap(); //changes from text mode to bitmap
Set_LCD_Pos(jet_x,jet_y);
Set_LCD_Char(3);
} else {
ALL_RED_LEDS_ON();
Set_Font_8_by_8();
lcd_display(LCD_LINE1, " PAUSED ");
}
}
Related
We have an embedded C programming assignment where we have to implement a state machine that changes a series of LED's depending on a Joystick Input. Two of the conditions are: "if Left LED is on and Down is Pressed Change to Right LED" and "if Right LED is on and Down is Pressed Change to Left LED". I know how to turn on certain LED's on button presses but I have no idea how to check the state of a GPIO pin/LED and change another LED based on the state when the joystick is used. I basically just want to know how to "call" the state of an LED.
This is the state machine sample code so far:
void
StateMachine ()
{
// REPLACE THE FOLLOW CODE WITH YOUR SOLUTION
// This code just toggles top LED and set left or right LED.
//
// Solution.
uint8_t Joystick;
uint8_t Toggle = 0;
while (1)
{
Joystick = GetJoystick();
if (Joystick == 'L')
{
WriteLED ('L', LED_ON);
WriteLED ('R', LED_OFF);
}
else if (Joystick == 'R')
{
WriteLED ('L', LED_OFF);
WriteLED ('R', LED_ON);
}
if (Toggle == 0)
{
WriteLED ('T', LED_ON);
Toggle = 1;
}
else
{
WriteLED ('T', LED_OFF);
Toggle = 0;
}
}
}
Update: This is my WriteLED method
void
WriteLED (uint8_t LED, uint8_t State)
{
// Check for correct state
if ((State != LED_OFF) && (State != LED_ON))
{
return;
}
// Turn on/off the LED
switch (LED)
{
case 'L':
HAL_GPIO_WritePin (LD4_GPIO_Port, LD4_Pin, State);
break;
case 'T':
HAL_GPIO_WritePin (LD3_GPIO_Port, LD3_Pin, State);
break;
case 'B':
HAL_GPIO_WritePin (LD6_GPIO_Port, LD6_Pin, State);
break;
case 'R':
HAL_GPIO_WritePin (LD5_GPIO_Port, LD5_Pin, State);
break;
}
return;
}
If the assignment is specifically asking for a "state machine" then the software should somehow have different internal "states" corresponding to the different LED output requirements. There are lots of ways to represent a state machine -- (were you shown one?) -- For example:
// enumeration of the required states
enum OutputState {
stateAllOff, // I'm *guessing* this is the required initial state?
stateLeftLED,
stateRightLED,
// ... any other states that are specified.
// ... but *not* random combinations of LEDs that are not part of the specification.
};
enum OutputState currentState = stateAllOff; // or whatever initial state is required
// [...] I'm not going to do the actual assignment here
A state machine doesn't have to read the LED states, it just "remembers" them in the currentState variable. Now the rest of the code becomes a straightforward implementation of the conditions you were given so...
"if Left LED is on and Down is Pressed Change to Right LED"
if (currentState == stateLeftLED) {
if (Joystick == "D") {
WriteLED ('R', LED_ON);
WriteLED ('L', LED_OFF);
currentState = stateRightLED;
}
}
STM's HAL library offers a ReadPin function analog to the WritePin function you already used.
It's declaration looks as follows:
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
Which means you could read the state of a certain pin like this:
GPIO_PinState ld6_state = HAL_GPIO_ReadPin(LD6_GPIO_Port, LD6_Pin);
GPIO_PinState is an enumeration:
typedef enum
{
GPIO_PIN_RESET = 0,
GPIO_PIN_SET
}GPIO_PinState;
All that's left is comparing the return value of the read function (ld6_state) to either of the enumeration values. As mentioned by the first answer you'll most likely experience some bouncing of your inputs which is caused by the mechanical construction of your buttons. I guess figuring out how to solve that is part of the assignment so I'll leave that up to you. Keywords to look for: debounce or debouncing
Normally the state of an GPIO is saved in a register variable. You either need a definition of this variable or a vector pointing to its adress to read (or manipulate) it directly. Do you have documentation of the method WriteLED? It could give you a hint.
If you don't find anything you could still implement a flag to indicate which LED you switched on most recently.
Generally the Embedded Programming depends highly on the Chip you are working with and the corresponding compiler.
So to give you a better answer, you should first provide important information like the Hardware and Software you are using and libraries you want to implement.
You likely want to put a delay in your main loop.
Unless your joystick function locks the code until it sees a change, that toggle on your top LED is going to happen so fast that you are likely to see a dim glow or perhaps even nothing at all depending on the rise time of your hardware.
Like Wizzard said you should be able to find the status of your LED by looking in a register. How this is done is totally down to your hardware.
It would also most likely be suitable to use a few static booleans so you can save the state of the LEDs and check these to get your LED values, but this is not a perfect implementation. Register checks are better.
I want to make debounce for two buttons. So turn on Red led or Green led knowing which button have pressed My program only works for 1 button.
I think that I need a array for two several buttons.
Could anyone help me to improve my code two buttons or more ?
int boton = 11;
int led = 13;
boolean estadoAnterior = LOW;
boolean estadoActual = LOW;
boolean ledOn = false;
int cont=0;
void setup()
{
pinMode(boton, INPUT);
pinMode(led, OUTPUT);
Serial.begin(9600);
}
boolean rebote(boolean eAnterior)
{
boolean eActual = digitalRead(boton);
if (eAnterior != eActual)
{
delay(5);
eActual = digitalRead(boton);
}
return eActual;
}
void loop()
{
estadoActual = rebote(estadoAnterior);
if (estadoAnterior == LOW && estadoActual == HIGH)
{
ledOn = !ledOn;
cont++;
Serial.println(cont);
}
estadoAnterior = estadoActual;
digitalWrite(led, ledOn);
}
Overall, using a busy-delay is a rather crude way to de-bounce buttons, but it will work for hobbyist purposes.
Change estadoAnterior into an array of expected button states.
Make an array of ints for the button pins boton. (In real MCU programming, this would be an array of ports + masks.)
In the debounce function, make an array of de-bounce bool values for buttons that need debouncing. Check which ones that need debouncing in a loop.
If any button needed debouncing, wait 5ms. Not per button, but once. (Btw 5ms may or may not be enough depending on button type)
Read that button again and use the result.
A more professional approach might be something along the lines of this.
Once done, rewrite all identifiers to English. We don't use our native language when programming, because that turns the source code into a mess. Your code is some mix of English and your native language, it is very hard to read.
I have this loop, how would I end the loop?
void loop() {
// read the pushbutton input pin:
a ++;
Serial.println(a);
analogWrite(speakerOut, NULL);
if(a > 50 && a < 300){
analogWrite(speakerOut, 200);
}
if(a <= 49){
analogWrite(speakerOut, NULL);
}
if(a >= 300 && a <= 2499){
analogWrite(speakerOut, NULL);
}
This isn't published on Arduino.cc but you can in fact exit from the loop routine with a simple exit(0);
This will compile on pretty much any board you have in your board list. I'm using IDE 1.0.6. I've tested it with Uno, Mega, Micro Pro and even the Adafruit Trinket
void loop() {
// All of your code here
/* Note you should clean up any of your I/O here as on exit,
all 'ON'outputs remain HIGH */
// Exit the loop
exit(0); //The 0 is required to prevent compile error.
}
I use this in projects where I wire in a button to the reset pin. Basically your loop runs until exit(0); and then just persists in the last state. I've made some robots for my kids, and each time the press a button (reset) the code starts from the start of the loop() function.
Arduino specifically provides absolutely no way to exit their loop function, as exhibited by the code that actually runs it:
setup();
for (;;) {
loop();
if (serialEventRun) serialEventRun();
}
Besides, on a microcontroller there isn't anything to exit to in the first place.
The closest you can do is to just halt the processor. That will stop processing until it's reset.
Matti Virkkunen said it right, there's no "decent" way of stopping the loop. Nonetheless, by looking at your code and making several assumptions, I imagine you're trying to output a signal with a given frequency, but you want to be able to stop it.
If that's the case, there are several solutions:
If you want to generate the signal with the input of a button you could do the following
int speakerOut = A0;
int buttonPin = 13;
void setup() {
pinMode(speakerOut, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
}
int a = 0;
void loop() {
if(digitalRead(buttonPin) == LOW) {
a ++;
Serial.println(a);
analogWrite(speakerOut, NULL);
if(a > 50 && a < 300) {
analogWrite(speakerOut, 200);
}
if(a <= 49) {
analogWrite(speakerOut, NULL);
}
if(a >= 300 && a <= 2499) {
analogWrite(speakerOut, NULL);
}
}
}
In this case we're using a button pin as an INPUT_PULLUP. You can read the Arduino reference for more information about this topic, but in a nutshell this configuration sets an internal pullup resistor, this way you can just have your button connected to ground, with no need of external resistors.
Note: This will invert the levels of the button, LOW will be pressed and HIGH will be released.
The other option would be using one of the built-ins hardware timers to get a function called periodically with interruptions. I won't go in depth be here's a great description of what it is and how to use it.
The three options that come to mind:
1st) End void loop() with while(1)... or equally as good... while(true)
void loop(){
//the code you want to run once here,
//e.g., If (blah == blah)...etc.
while(1) //last line of main loop
}
This option runs your code once and then kicks the Ard into
an endless "invisible" loop. Perhaps not the nicest way to
go, but as far as outside appearances, it gets the job done.
The Ard will continue to draw current while it spins itself in
an endless circle... perhaps one could set up a sort of timer
function that puts the Ard to sleep after so many seconds,
minutes, etc., of looping... just a thought... there are certainly
various sleep libraries out there... see
e.g., Monk, Programming Arduino: Next Steps, pgs., 85-100
for further discussion of such.
2nd) Create a "stop main loop" function with a conditional control
structure that makes its initial test fail on a second pass.
This often requires declaring a global variable and having the
"stop main loop" function toggle the value of the variable
upon termination. E.g.,
boolean stop_it = false; //global variable
void setup(){
Serial.begin(9600);
//blah...
}
boolean stop_main_loop(){ //fancy stop main loop function
if(stop_it == false){ //which it will be the first time through
Serial.println("This should print once.");
//then do some more blah....you can locate all the
// code you want to run once here....eventually end by
//toggling the "stop_it" variable ...
}
stop_it = true; //...like this
return stop_it; //then send this newly updated "stop_it" value
// outside the function
}
void loop{
stop_it = stop_main_loop(); //and finally catch that updated
//value and store it in the global stop_it
//variable, effectively
//halting the loop ...
}
Granted, this might not be especially pretty, but it also works.
It kicks the Ard into another endless "invisible" loop, but this
time it's a case of repeatedly checking the if(stop_it == false) condition in stop_main_loop()
which of course fails to pass every time after the first time through.
3rd) One could once again use a global variable but use a simple if (test == blah){} structure instead of a fancy "stop main loop" function.
boolean start = true; //global variable
void setup(){
Serial.begin(9600);
}
void loop(){
if(start == true){ //which it will be the first time through
Serial.println("This should print once.");
//the code you want to run once here,
//e.g., more If (blah == blah)...etc.
}
start = false; //toggle value of global "start" variable
//Next time around, the if test is sure to fail.
}
There are certainly other ways to "stop" that pesky endless main loop
but these three as well as those already mentioned should get you started.
This will turn off interrupts and put the CPU into (permanent until reset/power toggled) sleep:
cli();
sleep_enable();
sleep_cpu();
See also http://arduino.land/FAQ/content/7/47/en/how-to-stop-an-arduino-sketch.html, for more details.
just use this line to exit function:
return;
I'm attempting to write a function that will pull text from different sources (Ethernet client/Serial/etc.) into a single line, then compare them and run other functions based on them. Simple..
And while this works, I am having issues when trying to call a simple Serial.println() from a function OTHER than loop().
So far, I have around 140 lines of code, but here's a trimmed down version of the portion that's causing me problems:
boolean fileTerm;
setup() {
fileTerm = false;
}
loop() {
char character;
String content="";
while (Serial.available()) {
character = Serial.read();
content.concat(character);
delay(1);
}
if (content != "") {
Serial.println("> " + content);
/** Error from Serial command string.
* 0 = No error
* 1 = Invalid command
*/
int err = testInput(content);
}
int testInput(String content) {
if (content == "term") {
fileTerm = true;
Serial.println("Starting Terminal Mode");
return 0;
}
if (content == "exit" && fileTerm == true) {
fileTerm = false;
Serial.println("Exiting Terminal Mode");
return 0;
}
return 1;
}
(full source at http://pastebin.com/prEuBaRJ)
So the point is to catch the "term" command and enter some sort of filesystem terminal mode (eventually to access and manipulate files on the SD card). The "exit" command will leave the terminal mode.
However, whenever I actually compile and type these commands with others into the Serial monitor, I see:
> hello
> term
> test for index.html
> exit
> test
> foo
> etc...
I figure the function is catching those reserved terms and actually processing them properly, but for whatever reason, is not sending the desired responses over the Serial bus.
Just for the sake of proper syntax, I am also declaring the testInput() function in a separate header, though I would doubt this has any bearing on whether or not this particular error would occur.
Any explainable reason for this?
Thanks.
Model: Arduino Uno R3, IDE version: 1.0.4, though this behavior also happened on v1.0.5 in some instances..
It is kinda guessable how you ended up putting delay(1) in your code, that was a workaround for a bug in your code. But you didn't solve it properly. What you probably saw was that your code was too eager to process the command, before you were done typing it. So you slowed it down.
But that wasn't the right fix, what you really want to do is wait for the entire command to be typed. Until you press the Enter key on your keyboard.
Which is the bug in your code right now, the content variable doesn't just contain "term", it also contains the character that was generated by your terminal's Enter key. Which is why you don't get a match.
So fix your code, add a test to check that you got the Enter key character. And then process the command.
I'm programming a robot, and unfortunately in its autonomous mode I'm having some issues.
I need to set an integer to 1 when a button is pressed, but in order for the program to recognize the button, it must be in a while loop. As you can imagine, the program ends up in an infinite loop and the integer values end up somewhere near 4,000.
task autonomous()
{
while(true)
{
if(SensorValue[positionSelectButton] == 1)
{
positionSelect = positionSelect + 1;
wait1Msec(0350);
}
}
}
I've managed to get the value by using a wait, but I do NOT want to do this. Is there any other way I can approach this?
assuming that the SensorValue comes from a physical component that is asynchronous to the while loop, and is a push button (i.e. not a toggle button)
task autonomous()
{
while(true)
{
// check whether
if(current_time >= next_detect_time && SensorValue[positionSelectButton] == 1)
{
positionSelect = positionSelect + 1;
// no waiting here
next_detect_time = current_time + 0350;
}
// carry on to other tasks
if(enemy_is_near)
{
fight();
}
// current_time
current_time = built_in_now()
}
}
Get the current time either by some built-in function or incrementing an integer and wrap around once reach max value.
Or if you are in another situation:
task autonomous()
{
while(true)
{
// check whether the flag allows incrementing
if(should_detect && SensorValue[positionSelectButton] == 1)
{
positionSelect = positionSelect + 1;
// no waiting here
should_detect = false;
}
// carry on to other tasks
if(enemy_is_near)
{
if(fight() == LOSING)
should_detect = true;
}
}
}
Try remembering the current position of the button, and only take action when its state changes from off to on.
Depending on the hardware, you might also get a signal as though it flipped back and forth several times in a millisecond. If that's an issue, you might want to also store the timestamp of the last time the button was activated, and then ignore repeat events during a short window after that.
You could connect the button to an interrupt and then make the necessary change in the interrupt handler.
This might not be the best approach, but it will be the simplest.
From The Vex Robotics catalogue :
(12) Fast digital I/O ports which can be used as interrupts
So, most probably which ever micro-controller of Vex you are using will support Interrupts.
Your question is a bit vague
I m not sure why u need this variable to increment and how things exactly work...but i ll make a try.Explain a bit more how things work for the robot to move...and we will be able to help more.
task autonomous()
{
int buttonPressed=0;
while(true)
{
if(SensorValue[positionSelectButton] == 1)
{
positionSelect = positionSelect +1;
buttonPressed=1;
}
else{
buttonPressed = 0;
}
//use your variables here
if( buttonPressed == 1){
//Move robot front a little
}
}
}
The general idea is :
First you detect all buttons pressed and then you do things according to them
All these go in your while loop...that will(and should) run forever(at least as long as your robot is alive :) )
Hope this helps!