I have used a switch case in my Arduino project and also I have used a for loop on my second case, but the function is not getting out of the for loop. I want to run my second case only for 5sec then wants to break it. Help me with that.
int cmd;
void loop(){ // run over and over again
if(Serial.available()){
Serial.println("enter 1 or 2");
cmd=Serial.read();
switch (cmd){
case '1':
function1() ;
break ;
case '2':
int i=0;
for(i=0;i<100;i++){
function2();
delay(50);
}
break;
}
}
}
Your loop will always take more then 5 seconds to complete as your total delay is 5 seconds plus the execution time of function2. If it is not exiting the loop, my bet would be that your function2 is responsible for that.
Anyway, if you need timing, you should use the millis() funcion, the result would be something like this:
long startTime = millis();
long delay = 50000;
while(millis() < startTime + delay){
functionw();
}
This implementation would be much more closer to your 5 second time limit.
Related
I need help looping a loop random amount of time.
For example:
for (int i = 0; i <= 10; i++) {
//Blah blah code
}
This, I believe loops it 10 times. I want it to loop a random amount of times so I tried this:
for (int i = 0; i <= random(0,1000); i++) {
//Blah blah code
}
This hasn't worked for me, and it only picks randomly when I first power the arduino. When I close it and try it again, it loops it the same amount of times as before, and so forth. My question is, what am I doing wrong?
There is already a loop present as void loop. you should not use another loop inside a loop. Try to avoid it if it is avoidable.
Here is the example code you can use for your problem.
long randNumber;
void setup() {
Serial.begin(9600);
randomSeed(analogRead(0)); // seeding random input from analog pin , one can use any analog pin.
}
void loop() {
randNumber = random(300);
Serial.println(randNumber);
delay(50);
}
This is my code:
#include <wiringPi.h>
#include <stdio.h>
#define LED 18
#define IN 24
int main(void)
{
wiringPiSetupGpio ();
pinMode (LED, OUTPUT);
pinMode (IN, INPUT);
for (;;)
{
digitalWrite (LED, 1);
delay (2000);
digitalWrite (LED, 0);
delay (2000);
if (digitalRead (IN) == 1)
{
for (;;)
{
digitalWrite (LED, 1);
delay(500);
digitalWrite (LED, 0);
delay(500);
}
}
}
return 0;
}
I use a switch to go from the 2000 delay to the 500 delay. The problem is that when I press the switch it waits until the loop is over until it becomes faster. Same applies to vice versa. I need to write a function or a loop somewhere in my code that allows me to press the switch and immediately with no wait go to the slower/faster speed. I am coding this in C, on a raspberry pi using the wiring pi libraries, and gpio pin numbering.
First things first, that code as you've shown it will never deviate from a delay of 2000 simply because there's no way to exit from the initial for(;;) loop. That's probably the first thing you need to check and fix.
In terms of being able to end a delay early, you can do something like change:
delay (2000);
into:
for (i = 0; i < 2000; i += 10) {
delay (10);
if (digitalRead (IN) == 1)
break;
}
This basically exits the delay early if the switch changes, so that you'll never be waiting more than 10 time units (rather than up to 2000).
Just be aware that there may be an overhead to repeatedly calling delay. In other words, while delay(2000) may take very close to 2000 time units, two hundred calls to delay(10) may take a little more because of setup time for each call and so on.
In fact, you can probably greatly simplify your code by not using hard-coded values at all. Instead, you can have a single loop with minimal delay, with some internal controls which work out when and how to change the LED (i.e., not every time through the loop).
For example, something like this would do it. I haven't tested it since my Pi2 is still sitting in a box awaiting some time for me to play with it, but it should be pretty close:
#include <wiringPi.h>
#include <stdio.h>
#define LED 18
#define IN 24
#define RES 10
int main (void) {
int cycleTime, ledState, lastSwitch, currSwitch, timeLeft;
wiringPiSetupGpio ();
pinMode (LED, OUTPUT);
pinMode (IN, INPUT);
cycleTime = 2000; // Initial cycle time
ledState = 0; // and LED state.
lastSwitch = 0; // Previous switch state,
// Start infinite loop with first cycle time.
timeLeft = cycleTime;
for (;;) {
// Delay for minimal time and adjust time left.
delay (RES);
timeLeft = timeLeft - RES;
// Detect switch change.
currSwith = digitalRead (IN);
if (currSwitch != lastSwitch) {
// If so, store new state, change cycle time
// and force IMMEDIATE end of current cycle.
lastSwitch = currSwitch;
cycleTime = 2500 - cycleTime; // switch 500 <-> 2000
timeLeft = 0;
}
// Detect end of cycle.
if (timeLeft <= 0) {
// Toggle LED and start new cycle.
ledState = 1 - ledState;
digitalWrite (LED, ledState);
timeLeft = cycleTime;
}
}
}
Basically, you have a single loop but one which loops every ten time units rather than every 500 or 2000. You maintain a separate counter which decides when the LED should be flipped and the starting value for this counter depends on the current cycle time.
When the switch is flipped, that counter is zeroed so that it (almost) immediately changes to the next cycle.
For the last two days i wrote a program that in basic terms generates a fairly accurate user adjustable pulse signal (both frequency and duty cycle adjustable). It basically uses the micros() function to keep track of time in order to pull low or high the 4 digital output channels.
These 4 channels need to have a phase difference of 90 degrees (think a 4cyl engine) always. In order for the user to change settings an ISR is implemented which returns a flag to the main loop to re-initialise the program. This flag is defined as a boolean 'set4'. When it is false a 'while' statement in the main loop will run the outputs. When it is true an 'if' statement will perform the necessary recalculations and reset the flag so that the 'while' statement will resume.
The program works perfectly with the initial values. Phase is perfect. However when the ISR is called and comes back to the main loop, from how i understand it resumes the program in the 'while' statement from where was originally interrupted, until it finishes and re-checks the flag 'set4' to see it is now true and it should stop.
Then, even though the 'if' statement afterwards resets and re-calculates all the necessary variables the phase between these 4 output channels is lost. Tested manually i see depending on which time the ISR is called it will give different results, usually having all 4 output channels synchronised together!
This happens even though i might don't change any values (thus the 'if' routine resets the variables to exactly the same ones when you first power up the arduino!). However, if i comment out this routine and just leave the line which resets the flag 'set4' the program will continue normally like nothing never happened!
I'm pretty sure that this is somehow caused because of the micros() timer because the loop will be resumed from where the ISR was called. I've tried to do it differently by checking and disabling for interrupts using cli() and sei() but i couldn't get it to work because it will just freeze when the arguments for cli() are true. The only solution that i can think of (i've tried everything, spend the whole day searching and trying out stuff) is to force the ISR to resume from the start of the loop so that the program may initialize properly. Another solution that comes to mind is to maybe reset the micros() timer somehow..but this would mess up the ISR i believe.
To help you visualise what is going on here's a snip of my code (please don't mind the 'Millis" name in the micros variables and any missing curly brackets since it is not pure copy-paste :p):
void loop()
{
while(!set4)
{
currentMillis = micros();
currentMillis2 = micros();
currentMillis3 = micros();
currentMillis4 = micros();
if(currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (ledState == LOW)
{
interval = ONTIME;
ledState = HIGH;
}
else
{
interval = OFFTIME;
ledState = LOW;
}
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
}
.
.
//similar code for the other 3 output channels
.
.
}
if (set4){
//recalculation routine - exactly the same as when declaring the variables initially
currentMillis = 0;
currentMillis2 = 0;
currentMillis3 = 0;
currentMillis4 = 0;
//Output states of the output channels, forced low seperately when the ISR is called (without messing with the 'ledState' variables)
ledState = LOW;
ledState2 = LOW;
ledState3 = LOW;
ledState4 = LOW;
previousMillis = 0;
previousMillis2 = 0;
previousMillis3 = 0;
previousMillis4 = 0;
//ONTIME is the HIGH time interval of the pulse wave (i.e. dwell time), OFFTIME is the LOW time interval
//Note the calculated phase/timing offset at each channel
interval = ONTIME+OFFTIME;
interval2 = interval+interval/4;
interval3 = interval+interval/2;
interval4 = interval+interval*3/4;
set4=false;
}
}
Any idea what is going wrong?
Kind regards,
Ken
The problem is here:
previousMillis = 0;
previousMillis2 = 0;
previousMillis3 = 0;
previousMillis4 = 0;
All if statement will be true on the next loop.
Try with:
previousMillis = micros();
previousMillis2 = micros();
previousMillis3 = micros();
previousMillis4 = micros();
I am making a program in which I am getting data from a serial device. The problem which I am facing is that the device gives me the wrong data until I run while(1) and then read the data. So I thought of running a for loop for 100000 times and then reading the data but still it was giving wrong data. I can only use while(1). So is there anyway I can stop while(1) after sometime like 7-10sec.?
please help,thanks.!!
I think it will help.
int i=0;
while(1){
// do your work.
if ( i == 100 ) break; // for an example.
i++;
}
printf("After While\n");
Is it necessary for your while loop to iterate on 1? Perhaps you could loop on time(NULL) instead, for example:
time_t t = time(NULL) + 10;
while (time(NULL) < t) {
/* ... */
}
This is not exactly precise; The loop could run for anything between 9 seconds and 10 seconds, perhaps even longer depending on how saturated your CPU usage is by other tasks. It doesn't look like you're looking for anything precise, however, and this should give you some idea...
If for whatever silly reason you must use while (1), then you can use this idea together with if and break like so:
time_t t = time(NULL) + 10;
while (1) {
if (time(NULL) >= t) {
break;
}
/* ... */
}
To exit the loop you have to use break statement.
while(1)
{
//your code...
sleep(7);//to sleep for 7 seconds
break;//jumps out of the loop after 7 seconds of delay
}
#include <time.h>
#include <stdio.h>
int main()
{
time_t end = time(NULL) + 7; //7s
while (1) {
//your code...
printf("running...\n");
if (time(NULL) >= end) {
break;
}
//your code..
}
return 0;
}
while(1) {
delay(10000); //To delay for 10 seconds.
break;
}
If you can't use delay() then probably use some loop to get significant amount of time delay and thereafter break the loop.
How would I output text one letter at a time like it's typing without using Sleep() for every character?
Sleep is the best option, since it doesn't waste CPU cycles.
The other option is busy waiting, meaning you spin constantly executing NoOps. You can do that with any loop structure that does absolutely nothing. I'm not sure what this is for, but it seems like you might also want to randomize the time you wait between characters to give it a natural feel.
I would have a Tick() method that would loop through the letters and only progress if a random number was smaller than a threshold I set.
some psuedocode may look like
int escapeIndex = 0;
int escapeMax = 1000000;
boolean exportCharacter = false;
int letterIndex = 0;
float someThresh = 0.000001;
String typedText = "somethingOrOther...";
int letterMax = typedText.length();
while (letterIndex < letterMax){
escapeIndex++;
if(random(1.0) < someThresh){
exportCharacter = true;
}
if(escapeIndex > escapeMax) {
exportCharacter = true;
}
if(exportCharacter) {
cout << typedText.charAt(letterIndex);
escapeIndex = 0;
exportCharacter = false;
letterIndex++;
}
}
If I were doing this in a video game lets say to simulate a player typing text into a terminal, this is how I would do it. It's going to be different every time, and it's escape mechanism provides a maximum time limit for the operation.
Sleeping is the best way to do what you're describing, as the alternative, busy waiting, is just going to waste CPU cycles. From the comments, it sounds like you've been trying to manually hard-code every single character you want printed with a sleep call, instead of using loops...
Since there's been no indication that this is homework after ~20 minutes, I thought I'd post this code. It uses usleep from <unistd.h>, which sleeps for X amount of microseconds, if you're using Windows try Sleep().
#include <stdio.h>
#include <unistd.h>
void type_text(char *s, unsigned ms_delay)
{
unsigned usecs = ms_delay * 1000; /* 1000 microseconds per ms */
for (; *s; s++) {
putchar(*s);
fflush(stdout); /* alternatively, do once: setbuf(stdout, NULL); */
usleep(usecs);
}
}
int main(void)
{
type_text("hello world\n", 100);
return 0;
}
Since stdout is buffered, you're going to have to either flush it after printing each character (fflush(stdout)), or set it to not buffer the output at all by running setbuf(stdout, NULL) once.
The above code will print "hello world\n" with a delay of 100ms between each character; extremely basic.