Using CCS Toggle LED With Button - c

I didn't understand what is wrong with my code. Here what I am trying to do is toggle a led when I press button. And I count my button hits with int count;.
If the count number is even LED is high and else LED is low. But when I upload this program, LED stays on. And off only while I hold the button.
while(1){
int buttonState=input_state(pin_a0);
if(buttonState != lastButtonState){
count++;
lastButtonState=buttonState;
if(count%2==0){
output_high(pin_b0);
}
else
output_low(pin_b0);
}
delay_ms(50);
}

There is a problem in your logic. You have two changes while pressing the button. The first change is from 0 to 1 (pressing) and the second change is from 1 to 0 (releasing the button).
Try something like:
if(lastButtonState == 0 && buttonState == 1)

Is your button active-high or active-low ? Is your LED powered active-high or active-low? You need to give that information.
I'll give an explanation assuming LED is powered when output is low. Then what follows is, assuming button is active-low, when your button is not pressed,
buttonState = 1;
So, since
lastButtonState = 0;
(at the start of the program, I'm assuming)
You will enter the if clause:
if(buttonState != lastButtonState){
...
}
This will increase your counter by one and make lastButtonState = buttonState;
Since count%2 will be 1, your pin will be output_low(pin_b0);... So, at the start of your program, your LED will be ON.
If you then press the button,
buttonState=0;
will happen and you will enter the if() clause, again. This will increase your counter by one. And then:
count%2 = 0;
Will happen. So, you will have
output_high(pin_b0);
As you can see, when you press the button, your LED will go off. And on when you release the button, your LED will go on Try this:
while(1){
int buttonState=input_state(pin_a0);
if(buttonState != lastButtonState){
lastButtonState=buttonState;
if(buttonState == 1){
output_high(pin_b0); // LED is off
}
else
output_low(pin_b0); // LED is on
}
delay_ms(50);
}
You don't need the counter.
EDIT:
I see you have made this addition to your code:
if(buttonState==1)
count++;
This works. Yet is harder to understand. Try writing something easier to read.

Related

What should I do for stop the loop at the background when I am not pressing the button?

I am new here ,sooo sorry for the mistakes :P.
So whatever. I am trying to do a simple counter circuit with Arduino UNO, a catot 7-segment display and a button. I just want to when I press the button system circle start and takes one footstep. For example 7-segment shows "0" from earlier push, when ı push the button it needs to be "1". But ıdk why its keep counting from background and I couldn't stop it. Then I make some adjustments in my code( btw ı am coding in micro-c for AVR and using AVRDUDES for load my code in Arduino.) and then its stuck at "F" (System should count like 1,2,3,4,5,6,7,8,9,A,b,c,d,E,F). I don't understand why and how can I solve it. Additionally 7 segment led connected with my D port. I want to do B0 pin is input. Then I want to control the B0 pin's value. When B0 pin is HİGH, then i want to program continue.
unsigned char dizi[] = {0x40,0xF9,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x08,0x03,0x27,0x21,0x06,0x0E};
unsigned int i ;
void main()
{
DDRD = 0xFF ;
DDB0_bit = 0 ;
while(PINB.B0);
{
for(i = 0;i<=15;i++)
{
PORTD = dizi[i] ;
Delay_ms(700);
}
}
}
I just write the code and just ıdk ı hope it work. But it didn't. Idk why and my mind is so blurry ı can't see the error. I hope u can help :D.
What are you using to program your Arduino?
The loop never stops after you press the button because you don't have a stop condition aside from i reaching 15. I'm rusty on Arduino but you could add
if(!(PINB.B0)){ break; }
in the for loop, after the delay to exit the loop when you're not pressing the button.
Your program needs to work like this:
for(;;) { /* program here */ } Microcontroller programs never leave main().
You need to read the button and then debounce it. This should be mentioned in any embedded systems beginner tutorial. Debouncing is mandatory whenever you have a button, or the program will just behave randomly, sometimes missing keyboard presses, other times taking several at once etc.
(The most proper way to do this is to read the button repeatedly from a timer callback, but then you need to write the code for the timer/RTC hardware peripheral driver first.)
Once you have a debounced signal pressed/not pressed, then implement a simple state machine like in this pseudo code:ish C below:
typedef enum
{
NOT_PRESSED,
PRESSED_UPDATE_DISPLAY,
PRESSED_STILL_DISPLAYED,
} simple_state_machine_t;
simple_state_machine_t state = NOT_PRESSED;
...
int index_7seg = 0;
for(;;)
{
/* debounce button */
bool is_pressed = debounced_value;
switch(state)
{
case NOT_PRESSED:
state = is_pressed ? PRESSED_UPDATE_DISPLAY : NOT_PRESSED;
break;
case PRESSED_UPDATE_DISPLAY:
index_7seg++;
if(index_7seg == max_7seg)
{
index = 0;
}
state = is_pressed ? PRESSED_DISPLAYED : NOT_PRESSED;
break;
case PRESSED_DISPLAYED:
state = is_pressed ? PRESSED_DISPLAYED : NOT_PRESSED;
break;
}
PORTD = the7seg_table[index_7seg];
} /* for(;;) */
The PRESSED_UPDATE_DISPLAY state will only get entered when you go from not pressed to pressed, essentially giving you a rising edge trigger through software. That's the only time you should increase the table index.

Detecting rising and falling temperature C

I'm trying to detect rising and falling temperatures using PIC16F877A MCU and two DS8B20 sensors. I'm facing with problems when I try to detect temperature falling. Here is my code what am I trying to do:
#include "main.h"
void main() {
//Turn on LCD backlight
output_high(PIN_D7);
// Initialize LCD module
lcd_init();
float Threshold_Value = 30; // Temperature threshold value
while (TRUE) {
Show_User_Info();
delay_ms(10);
Read_Sensors();
// Starting to read user button values
User_Buttons();
delay_ms(20); // Minimum amount of time to read user button values
// Starting to compare user set temperature value and upper sensor temperature read value.
Compare_Upper_Temp();
delay_ms(20);
//================================
// Checking, if the MCU pin connected to pump is high. If yes - do the waiting 'animation'
if (input(PIN_B5)) {
while(temp > Threshold_Value);
{
Bottom_Waiting_Animation();
}
// Experimenting....
// break;
// continue;
}
if (input(PIN_B5)) {
while(temp < Threshold_Value);
{
Bottom_Waiting_Animation();
}
// break;
}
// If the set temp is less than threshold - turn the pump off.
if (temp < Threshold_Value) {
input(PIN_B5) == 0;
}
}
}
When the pump is switched on, I need to wait until second sensor reaches threshold value (30C), after that I need to 'detect' when that temperature starts to drop from that 30C. This code which I uploaded 'works' only with one While(temp > Threshold_Value) loop. But when I insert the next one under it while(temp < Threshold_Value), MCU jumps in undefined area and gets stuck. This task sounds pretty easy, but I tried lots of different ways to solve this problem. Maybe one of the problem reasons could be multiple while loops?
Don't use a semicolon after the while condition.
Replace
while (condition);
{
... looped code ...
}
with
while (condition)
{
.... looped code ...
}
This is one reason I like to put open braces at the end of the condition (as you do in your if statements): it helps to see the obnoxious accidental semicolon.

Value being reset in while loop [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am very new to this programming, trying to seta project up on proteus to add, minus and set an alarm through the use of buttons connected to a PIC. Issue is the count is not saving after the while loop and is being reset.
- button1= ADD, button2=MINUS, button 1+2+3 = ALARM
- cant figure out why overall count is being reset to 0
- Any help would be amazing
#include <main.h>
#ZERO_RAM
int a = 0;
int state;
char data = 'y';
short int flags[3];
char uart_rd;
void main()
{
setup_wdt(WDT_1MS); //~1.0 ms reset
port_a_pullups(0xFF); // Defining PORTA as pullup Resistors
printf("program start" nr); //<------keeps resetting value to 0 HERE
while (TRUE) // infinite loop
{
if (!input(PIN_A1)) // add button
{
if (!flags[0])
{
flags[0] = 1;
a++; // add one to overall count
printf("ADDED, Total= %dnr", a); // prints count
}
}
else
{
flags[0] = 0;
}
if (!input(PIN_A2)) // minus button
{
if (!flags[1])
{
flags[1] = 1;
a--; // take away 1 from count
printf("MINUS, Total= %dnr", a); // print count
}
}
else
{
flags[1] = 0;
}
if ((!input(PIN_A1)) && (!input(PIN_A2)) && (!input(PIN_A3))) // all buttons equal alarm
{
printf("ALARM HAS BEEN SETnr"); // if all buttons are held constant alarm
// is printed through Terminal
}
else
{
flags[2] = 0;
output_high(PIN_A0); // led goes high
delay_ms(500); // flashing LED every cycle
output_low(PIN_A0); // led goes low
printf("Overall Count= %dnr", a); // printf overall count
}
}
}
You have the following bugs:
You never initialize flags anywhere. Sure, static storage duration variables are required by the standard to be initialized to zero. But in embedded systems, there is an incredibly common non-standard extension which removes the "zero-out" part from the start up code. When you create a project you often get an option "minimal startup" or "standard C". Therefore, always initialize all your variables manually in run-time before using them. Robust embedded code makes no assumptions about the default values of variables in neither .datanor .bss segments.
You haven't implemented any debouncing. Please check some beginner tutorial about how to read buttons in embedded systems, to avoid problems with the electro-mechanical signal bounce. The signal bounce causes the code flags[0] = 0; to get executed.
Whenever someone presses a button, your condition for increasing the counter remains true for as long as the button is pressed. The microcontroller is fast enough to run that code many thousand times over during the time a slow human keeps the button pressed. Instead, you should only increase the counter when the button goes from inactive to active. Obviously, the code doing this needs to be located after the debouncing.

Selectively ignoring parts of a randomly generated sequence of numbers (in C)

I have a question that may be hard to understand -- but I will try my best to explain.
I'm programming the Simon Game in C. This implementation specifically read/writes to a hardware DAQ module that has a 4 LED display, and 4 corresponding toggle switches.
As per the rules of the Game, I've seeded and generated a random sequence of numbers between 0 and 3 (sequence length is arbitrarily 5). In the Game, if the player presses the wrong switch (i.e. blue is shown but you press green), the game ends and restarts.
The way I've set up the Game looks like this:
(I haven't included the code for function "blinkLED" here -- it turns the actual LED on/off.)
void runSimon(void){
int sequence[MAX_SEQ_LEN];
int i;
int count = 0;
// Seeds the random number generator.
srand((unsigned)time(NULL));
// Generate the random LED sequence & store it as an array.
for (i = 0; i < MAX_SEQ_LEN; i++){
sequence[i] = (rand() % NUM_LEDS);
}
// The game begins!
while (continueSuperLoop() == TRUE){
// Loop the game while the sequence length is less than the pre-defined maximum (currently it's 5).
while (count < MAX_SEQ_LEN){
for (i = 0; i <= count; i++){
// Blink the first 'count' LEDs in the sequence, one at a time.
blinkLED(sequence[i], 1, ONE_SEC);
//
//
//THE ISSUE SHOULD BE HERE (!)
//
// Monitors whether or not the player has made a mistake...if so, blink the red LED thrice, then restart the game.
if (digitalRead(sequence[ !i ] == SWITCH_ON)){
blinkLED(LED_1_R, 3, HALF_SEC);
Sleep(3 * ONE_SEC);
continue;
}
// Monitors whether or not the correct switch is being pressed -- waits for it to be released
while (digitalRead(sequence[i]) == SWITCH_ON){}
}
count++;
}
// If 'count' is equal to 'MAX_SEQ_LEN', the green LED blinks 3x to indicate the player has won .
if (count == MAX_SEQ_LEN){
blinkLED(LED_0_G, 3, HALF_SEC);
Sleep(3 * ONE_SEC);
}
}
}
Where I indicated an issue, I'm not sure how the "digitalRead(sequence[ ! i ]" behaves; I need this line to read every switch that's not supposed to be pressed.
I don't think the compiler understands what I'm trying to do here, though -- for example, if the first number in the sequence is 3 (representing the 4th LED), I need to specify that every other number (0, 1, 2) and its corresponding switch should not be pressed.
Would a solution be to store the current number in the sequence, having a set of four TRUE/FALSE flags for each LED, and monitoring the three non-current numbers and their corresp. switches to see if they are pressed?
I'm getting quite frustrated with writing this program. I'm pretty new to programming. Any help is appreciated.
I'm not sure I understand the rules of this game correctly but one thing that jumps out instantly is
digitalRead(sequence[ !i ]
I think you want
!digitalRead(sequence[ i ]
Also, you need to fix your game flow. Right now it's:
1. Light LED.
2. Check if user pressed the right button.
You need to wait for some time before checking a switch or wait for ANY switch to be pressed and see if it's the correct one. So something like this:
1. Light LED.
2. Wait for timeout or ANY switch to be pressed.
3. If timeout: error
4. else: check if switch that was pressed is correct.
In C, ! operator is a unary NOT. When applied to an integer i, it is equivalent to if (i == 0) return 1; else return 0;. Then you are using !i as an index for sequence array, so it will be either sequence[0] or sequence[1], and clearly this is not what you want. Also your == is inside of digitalRead call :)
I would suggest explicitly checking for every other button not to be pressed. Like this:
int isOtherPressed = 0;
for (ledId = 0; ledId < NUM_LEDS; ledId++) {
if (ledId != sequence[i] && digitalRead(ledId) == SWITCH_ON) {
isOtherPressed = 1;
}
}
if (isOtherPressed) {
// restart the game
}
However, I'm suspicious about the whole gameplay you have, but maybe it's just because I don't know how digitalRead works. For example, the way you use continue doesn't seem to stop the game. Maybe you meant break?

Do something, but check if button is clicked all the time

I have a arduino i want to blink some led light if the button is not clicked. Here is the code.
void startup(){
for (int x=0; x<=1;){
BUTTON5_state = digitalRead(START_BUTTON);
if (BUTTON5_state == HIGH ){
x++;
}
else{
blinkAll(1, 2000);
continue;
}
The problem is that its not checking the button often enough. The blink all 500 is waiting 2 seconds between each time it blinks. So you need to hold the button down for to seconds.
I want the light to blink every 2 second, but check the button "all the time". Is this possible?
Have you checked the "Blink Without Delay" tutorial in the Arduino IDE? Well, that's what you want to implement. Instead of using a delay (which is blocking) you poll the button as fast as possible and then, if millis() says that enough time has passed, you can blink.
delay is used when you want to wait; if you want to do something use other techniques.
An alternative is to use interrupts, but i suggest you to go with the first method...
2 possible solutions: create a thread, which checks the button and the original thread let the led blink. or you do the for loop faster and toggle the led only each 1000th iteration or so.
for example something like this:
for (int x=0; x<=100000;x++){
//wait to make the 1024 iteration blinking visible
BUTTON5_state = digitalRead(START_BUTTON);
if (BUTTON5_state == HIGH ){
break;
}
else if (x & (1 << 10)){ //each 1024th iteration
toggleLed();
}
}

Resources