I am setting up a slot machine with 3 squares that blink alternatively using double buffering; the while loop is infinite and stops using kbhit() (Which I believe is the mistake), even though the loop stops the commands in the if condition is not executed.
rectangle()-A function I wrote to make three squares spaced out equally on the screen.
while(z!=1)
{
if(kbhit()!=0)
{ cleardevice();
delay(3000);
bar3d((150),(110),(230),(190),0,0);
z=1;
continue;}
setvisualpage(page);
setactivepage(1-page);
settextstyle(3,0,5);
rectangle((x-190),y,(x+190),(y+60));
outtextxy((x-120),(y+3),"Slot Machine");
if(page==0)
setfillstyle(SOLID_FILL,4);
else
setfillstyle(SOLID_FILL,GREEN);
rectanfle(x,y);
setfillstyle(SOLID_FILL,BLUE);
bar3d((x-90),(y+255),(x+90),(y+295),5,5);
floodfill((x-89),(y+264),WHITE);
settextstyle(0,0,2);
outtextxy((x-85),(y+265),"Press Enter");
page=1-page;
delay(100);
}
Related
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 1 year ago.
Improve this question
i'm trying to learn coding and this has really stumped me so i thought i would ask you lovely people.
basically i'm trying to press a button and have an LED toggle on that is flashing on and off twice in a second, this will be continuous until i press the button again that will turn it off.
here is my code so far.
bool latch = false;
void setup(){
pinMode(1, INPUT);
pinMode(13, OUTPUT);
}
void loop(){
if (digitalRead(1)){
latch = !latch;
}
if (latch == 1){
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000);
}else{
digitalWrite(13, LOW)
}
}
Because of the calls to delay(1000), your code requires you to press the button in the exact split-second instant when digitalRead(1) is called. The Arduino cannot listen for button presses while delay() is in action. Also, you call delay(1000) twice, which flashes the LED on and off once in two seconds, not twice in once second.
The solution is to make a counter that counts how many milliseconds have passed since the last time the LED was toggled on or off. The loop will add 1 to counter every millisecond, so that when counter is equal to or greater than 500 (half a second), the LED toggles on or off.
Here is a program that starts blinking the LED (on-and-off in 1 second) when the button is pressed, and stops blinking when the button is pressed again. There are more explanations in the code.
bool latch = false;
bool led_state = false;
// How many milliseconds it has been since the last LED state change
int counter = 0;
void setup() {
pinMode(2, INPUT);
pinMode(13, OUTPUT);
}
void loop() {
// Check if the button was pressed
if (digitalRead(2)){
// If the button was pressed, wait half a second before toggling latch,
// to "de-bounce" the button (prevent it from sending multiple clicks for
// one press)
delay(300);
latch = !latch;
}
// If we are in on state (latch == true)...
if (latch) {
// ...add 1 to the counter and wait 1 millisecond...
counter += 1;
delay(1);
// ...and toggle the LED state if 500 milliseconds have passed.
// This we know because counter >= 500.
if (counter >= 500) {
if (led_state == true) led_state = false;
else if (led_state == false) led_state = true;
counter = 0;
}
digitalWrite(13, led_state);
// If we are in off state, turn the LED off
} else {
digitalWrite(13, false);
}
}
I did some experimenting with a simulator similar to what i assume you setup is(use this to setup your situation for future Arduino questions to make it easier for people to understand and help)
https://wokwi.com/arduino/projects/312378906051084864
Besides adding a missing semi-colon here, and working with what i assume your knowledge of programming is
Before
}else{
digitalWrite(13, LOW)
}
After
}else{
digitalWrite(13, LOW);
}
I made the small change to your if statement and this makes it work with some specific uses you must tap the button to turn it on and hold it when you think the interval is about to expire. This is because of your use of the delay function which basically stops all execution of your program until the interval is over. So the pin associated with you button must be high after the delay intervals and during if latch is evaluated
if (digitalRead(1)){
latch = true;
}else{
latch = false;
}
RECOMMENDED ALTERNATIVE
If you are interested in a better slightly more advance application of code i found this reference which provides a way to make a led blink without the use of the delay function
https://www.arduino.cc/en/Tutorial/BuiltInExamples/BlinkWithoutDelay
When using interrupts, any kind of digitalRead should be obsolete, or so i think. Let me explain my understanding of this to show my problem:
Say, a quadrature incremental rotary encoder (RE) is pulled up on both signal pins and is therefore idle HIGH. If i configure an interrupt service routine (ISR) on the falling edge on both pins and have the ISR for pin B do nothing more than set the flag "flag_B" to false (representing the logic state at the pin) and the ISR for pin A sets or resets a flag "flag_clockwise" depending on the state of flag_B during A's ISR, then i should get the right direction for every turning step, right? My only task is to then set the state of pin B to high again after the ISRs and my code should be ready for the next interrupt. But that doesn't work, with many random cases of the wrong direction being displayed or showing counter clockwise on the first half of the turning step when you can feel a little "bump" while turning the knob and then going clockwise on the second half, when the shaft has completed a single step, basically performing two opposite actions while only turning one step. Is my logic flawed?
All signals are debounced in hardware and look like expected on the oscilloscope.
ISRs:
//re-CLK signal
void IRAM_ATTR reCLK_ISR(void){
if(myFlags->pinBstate){
//this means the first interrupt of a turning step comes from the clock, not data
myFlags->direction = CCW;
}
else{
//this means the interrupt of a turning step occured from data first
myFlags->direction = CW;
}
}
//re-DATA signal
void IRAM_ATTR reDATA_ISR(void){
myFlags->pinDATAstate = false;
}
further processing:
//some function
//scroll = CW / CCW
if((myFlags->direction) != STOP){
if(myFlags->direction == CW){
//DEBUG
digitalWrite(PIN_LED_DEBUG, LOW);
}
}
if(myFlags->direction == CCW){
//DEBUG
digitalWrite(PIN_LED_DEBUG, HIGH);
}
myFlags->pinDATAstate = true;
myFlags->direction = STOP; //direction has 3 states: CW, CCW and STOP
}
the last 2 statements should restore all affected flags to the state before the encoder was touched, meaning ready for the next turn. The LED is just a replacement for different calculations which should be performed depending on the turning direction.
Even if the pin is assigned as interrupt, you can still use digitalRead() to determine the direction. For example:
const uint8_t pinA = 25;
const uint8_t pinB = 26;
volatile int counter;
void IRAM_ATTR isr(){
if(digitalRead(pinA) == digitalRead(pinB)) {
//Clockwise
counter++;
} else {
//Counter Clockwise
counter--;
}
}
You don't even need another ISR to determine the direction. I used this method to determine both the speed and the direction;
I want to make a program in which there are two dots blinking (with a break of 10ms) simultaneously, but one with delay 200ms and other with delay of 300ms. How can I play these two dots simultaneously from beginning? Is there a better way to that from following:
for(int i=1;i<100;i++)
{
if (i%2==0)
circle(10,10,2);
if (i%3==0)
circle(20,10,2);
delay(10);
cleardevice();
delay(100);
}
I would do something like this instead:
int t0=0,t1=0,t=0,s0=0,s1=0,render=1;
for (;;)
{
if (some stop condition like keyboard hit ...) break;
// update time, state
if (t>=t0) { render=1; s0=!s0; if (s0) t0+=10; else t0+=200; }
if (t>=t1) { render=1; s1=!s1; if (s1) t1+=10; else t1+=300; }
// render
if (render)
{
render=0;
cleardevice();
if (s0) circle(10,10,2);
if (s1) circle(20,10,2);
}
// update main time
delay(10); // Sleep(10) would be better but I am not sure it is present in TC++
t+=10;
if (t>10000) // make sure overflow is not an issue
{
t -=10000;
t0-=10000;
t1-=10000;
}
}
Beware the code is untested as I wrote it directly in here (so there might be syntax errors or typos).
The basic idea is having one global time t with small enough granularity (10ms). And for each object have time of event (t0,t1) state of object (s0,s1) and periods (10/200 , 10/300).
If main time reach the event time swap the state on/off and update event time to next state swap time.
This way you can have any number of objects just make sure your main time step is small enough.
The render flag just ensures that the scene is rendered on change only.
To improve timing you can use RDTSC instead of t+=10 and actually measure how much time has passed with CPU frequency accuracy.
To display the two circles simultaneously in the first round, you have to satisfy both conditions i%2==0 and i%3==0 at once. You can achieve it by simply changing
for(int i=1;i<100;i++)
to
for(int i=0;i<100;i++)
// ↑ zero here
I have an Arduino Uno set up to sense the light level and draw to a text file via Processing when it gets dark. I'd like to modify the Processing code to interrupt the draw loop for five seconds and then restart the draw loop. This will continuously write and overwrite the .txt file but that's not important right now.
The purpose of this excercise is to understand how to insert a break into the endless draw loop. I'm still very much a newbie to programming and am trying to wrap my head around how commands interact with eath other. Can anyone help me understand how to make this work? Eample code would be great but I'd also be happy with a conceptual description of how it's supposed to work...learn by doing and all.
I've tried putting the void draw() loop within a void loop() but it erred out. Am I on the right path?
<setup...mySerial and createWriter to path/file.txt>{
}
void draw() { //this is what needs to terminate & restart
if (mySerial.available() > 0 ) {
String value = mySerial.readString();
if ( value != null ) {
output.println( value );
}
}
}
void keyPressed and end
I believe what you're looking for is called a "state machine".
Make a variable that you can use to store a time value, then compare that to the current time to see if 5s have passed.
uint32_t last_trigger = 0; // millis() returns an unsigned, 32-bit integer
void setup()
{
Serial.begin(9600);
}
void loop()
{
if (millis() - last_trigger > 5000) { // 5000 milliseconds
last_trigger = millis(); // update last_trigger
Serial.print("last triggered at "); // report findings
Serial.print(last_trigger);
Serial.println(" milliseconds");
}
}
http://www.arduino.cc/en/Reference/Millis
If you aren't worried about really tight timing, the easy solution is to use the delay function. http://www.arduino.cc/en/Reference/Delay
The following might be a simple sketch that would do what you want. Adjust it as needed.
void setup()
{
Serial.begin(9600); // initialize serial routines
}
void loop()
{
int a = analogRead(0); // read the value of lightness
Serial.println(a); // tell processing what the value is
delay(5000); // wait for a 5 seconds
}
Can you give some examples of situations where a while loop and a if loop would be appropriate?
I am working on this project where an Arduino reads an analog input from a variable resistor.
This is how I have it read the raw input:
int intputValue = analogRead(A0);
Then I convert the raw input into a number between 0 and 100 for percentage:
double percentValue = inputValue * (1.0/10.23);
So then I use this percentValue to determine whether the Arduino needs to send signal(s) through several of its digital pins. I have signals going to a 4 channel relay module. Basically my idea is that if the percentValue is between 0-25, one of the relays would turn on, hence only one digital pin would need to be activated. Between 26-50, two pins, 51-75, three pins, and 76-100, four pins.
Here's my question: Should I use a if statement:
if(percentValue >=0 && percentValue <=25){
digitalWrite(pin1, HIGH); //turns on pin 1
}
Or use a while loop:
while(percentValue >= 0 && percentValue <=25){
digitalWrite(pin1, HIGH); //turns on pin 1
}
Then I'm going to do a similar thing for the rest of the percentValue ranges.
Is there a difference between using "if" and "while" in this case?
Thanks for any help.
There should be a setup and loop function in your code, you can put if in your loop function.
void setup() {
// put your setup code here, to run once:
int intputValue = analogRead(A0);
}
void loop() {
// put your main code here, to run repeatedly:
double percentValue = inputValue * (1.0/10.23);
if(percentValue >= 0 && percentValue <= 25){
digitalWrite(pin1, HIGH); //turns on pin 1
}
}
While loops are used to run a specific code block as long as certain parameters are met. An if statement is similar but it will only run the said code block once but a while statement will run until told otherwise.
So effectively:
while(1 == 1)
{
System.out.println("Hello World");
}
Will print Hello World indefinitely. On the other hand:
if(1 == 1)
{
System.out.println("Hello World");
}
Will print Hello World once.
Just for fun since your understanding of loops is shady; a for loop will run a specified number of times:
for(int i = 0; i < 3; i++)
{
System.out.println("Hello World");
}
Would print Hello World 3 times.
refer to:
While loop
For loop
If statement
General Java Tutorials
"Then I'm going to do a similar thing for the rest of the percentValue ranges."
This implies you should use an if statement, and not a while loop, especially if you want to do anything else with the device.
Presumably, this code will be placed in the Arduino loop() function, which is called repeatedly, giving you a loop. You don't want the Arduino to get stuck in a while loop of your own.
It appears that you want to light up different LEDs depending on the reading. You will want to turn off the other LEDs in the body of your if statements as well. Otherwise, the Arduino will just eventually have all 4 LEDs lit up.
if(percentValue >=0 && percentValue <=25){
digitalWrite(pin1, HIGH); //turns on pin 1
digitalWrite(pin2, LOW);
digitalWrite(pin3, LOW);
digitalWrite(pin4, LOW);
}
// etc.