Using a 8-bit AVR micro, I arrived to a simple situation which might not be that easy to solve.
Consider the following snippet:
static volatile uint8_t counter;
//fires often and I need all the values of the counter.
void isr(void) {
counter++;
}
int main (void) {
while(1) {
send_uart(counter);
counter = 0;
delay_ms(1000); //1 sec pause
}
return 0;
}
1.) It can happen that send_uart is followed by an isr which increases the counter, and then the next statement zeroes it out.
Therefore I'll miss one data from the counter.
2.) If I use ATOMIC_BLOCK(ATOMIC_RESTORESTATE) in the main fn, I can avoid the problems declared in (1), but it can happen that I miss an ISR because in this case INTs are disabled for a short time.
Is there a better way to pass information from the main fn to ISR?
If the counter is sampled rather than reset, there won't be any timing issues. Increments happening while sending will be accounted for in the next iteration. The unsigned data type of the counter variables will guarantee well-defined overflow behavior.
uint8_t cs = 0; // counter sample at time of sending
uint8_t n = 0; // counter as last reported
while (1) {
cs = counter; // sample the counter
send_uart((uint8_t)(cs - n)); // report difference between sample and last time
n = cs; // update last reported value
delay_ms(1000);
}
I am trying to get to figure out how to get this print function to work outside of the function the variable is in.
int altitude = 0;
void setup() {
Serial.begin(9600);
simulateAltitude();
}
void loop() {
Serial.println(altitude); // This does not work.
}
int simulateAltitude() {
int a = 0;
while ( a == 0 ) {
altitude += 1;
Serial.println(altitude); // This does work.
delay(1);
}
}
My biggest problem is the void loop() is not getting the value of altitude from the while loop in the int simulateAltitude function. This is being used on an Arduino UNO micro-controller board using C.
I am aware it is an infinite loop, it is for testing purposes only.
It's not printing the altitude from within loop() because loop() is never actually being called.
Remember this about Arduino. The setup() function is called once at boot time and, once it returns, the loop() function is called over and over again.
With the way you have it, your setup() function calls simulateAltitude() which goes into an infinite loop, so it never returns. It does not run simulateAltitude() and loop() concurrently.
You might be better off looking at something like:
void loop() {
Serial.println(altitude);
increaseAltitude();
}
int increaseAltitude() {
altitude += 1;
delay(1);
}
You have 2 problems here:
First of all, you need to initialize a and altitude. Give them initial values (say, 0).
Second, you didn't setup your Serial Monitor. Add this line to your setup function:
Serial.begin(9600); //9600 is more common but you can set other update frequencies
There are two problems in this code. The first is that simulateAltitude will never be called, so altitude will never update. The second problem is that neither a nor altitude are actually initialized.
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.
in my next project i use 4 Leds with delay(10000). I need a function for cancel this loop and start again with a new delay value e.g. 100.
I have enabled interrupts and when i pressed a button, delay changed to 100 AFTER a round. I have to wait 10 seconds.. It is possible to restart the loop function with the new values?
Wow that was rude ignacio
At least be helpful.
You can do this but not as you have implemented.
Delay is not good to be used in this circumstance. A much better way of implementing is to use a while loop like this:
int delayLED = 10000;
int beginMillis = millis();
while( millis() - beginMillis < delayLED)
{
// insert the code for your "interrupt" here
// kinda like this
if(button pressed)
{
delayLED = 100;
break;
}
}
This is just a template not a complete answer.
Let me know if you have further questions.
Happy coding!
I am working on an Arduino project controlling a DIY RC truck that reads the output pins of an RC reciever and is supposed to PWMs a couple of pins accordingly. The pins are hooked onto a motor controller that takes PWM.
That is where the problem comes in. My reverse is working perfectly, but on the pin that does forward, I only get random activity. I'm using the Arduino Mega 2560.
Here is the code. The problem has been posted below it:
#include <Servo.h>
//Create variables for three channels
int RXCH[3];
volatile int RXSG[3];
int RXOK[3];
int PWMSG[3];
byte vooruit;
byte achteruit;
Servo stuur;
int mv = 13;
int ma = 10;
void setup() {
Serial.begin(115200);
stuur.attach(8);
//Assign PPM input pins. The receiver output pins are conected as below to non-PWM Digital connectors:
RXCH[0] = 6; //Throttle
RXCH[1] = 7; //Steering
//RXCH[2] = 5; //Nothing yet
//RXCH[3] = 2; //Nothing yet
//RXCH[4] = 7; //Nothing yet
//RXCH[5] = 8; //Nothing yet
for (int i = 0; i < 3; i++){
pinMode(RXCH[i], INPUT);
}
//TCCR1B = TCCR1B & 0b11111000 | 0x01;
//TCCR2B = TCCR2B & 0b11111000 | 0x01;
}
void loop() {
// Read RX values
for (int i = 0; i < 3; i++){ //For each of the 6 channels:
RXSG[i] = pulseIn(RXCH[i], HIGH, 20000); //Read the receiver signal
if (RXSG[i] == 0) { //Error catching
RXSG[i] = RXOK[i];
} else {
RXOK[i] = RXSG[i];
}
//Substitute the high values to a value between -255 and 255
PWMSG[0] = map(RXSG[0], 1000, 2000, -255, 255);
//Servo values, calibrated according to my steering servo.
PWMSG[1] = map(RXSG[1], 1000, 2000, 24, 169);
//Make sure that the value stays within the desired boundaries.
constrain (PWMSG[i], -255, 255);
//For debugginf purposes
Serial.print(" || Ch: ");
Serial.print(i);
Serial.print(" / PWMSG: ");
Serial.print(PWMSG[i]);
}
delay (5);
// Car goes forwards
if (PWMSG[0] > 40)
{
MV();
}
// Car goes backwards
if (PWMSG[0] < -40)
{
MA();
}
// Car stops
else
{
stopmotor();
}
stuur.write(PWMSG[1]);
Serial.println();
}
void MV()
{
vooruit = PWMSG[0];
analogWrite (mv, vooruit);
digitalWrite (ma, LOW);
Serial.print(" vooruit: ");
Serial.print(vooruit);
}
void MA()
{
achteruit = abs(PWMSG[0]);
analogWrite (ma, achteruit);
digitalWrite (mv, LOW);
Serial.print(" achteruit: ");
Serial.print(achteruit);
}
void stopmotor()
{
digitalWrite (ma, LOW);
digitalWrite (mv, LOW);
}
I don't really know if the code is considered pretty, or if I made some basic mistakes for that matter.
This is one of my first projects that I tried to do the right way, making comments and such, all well commented criticism is welcome.
What the code is supposed to do:
Move the stick on the transmitter forwards, the car goes forwards, and speed should be according to position of the stick.
Move the stick on the transmitter backwards, the car goes backwards, and speed should be according to position of the stick.
Move stick on the transmitter left or right, the servo in the car should react according to the value the Arduino calculated. You might wonder why I don't place the servo directly on the transmitter. Well, that's because I have many more future things in mind with this project, and now I can calibrate it way easier.
Problem:
When I move the stick on the transmitter forwards, and the Serial monitor is open, I get the right values on the Serial monitor, but the LED present on pin 13 just randomly blinks, very dim I must say.
I already tried to replace things like byte with int, but it had no effect. The rest of the code works fine.
Using some new code, I get a Serial response from every "stage", except the final stages that controls the pins.
#include <Servo.h>
//Create variables for channels
Servo wheel;
int MFORWARD_PIN = 13;
#define MBACKWARD_PIN 10
#define WHEEL_PIN 8
#define THROTTLE_PIN 6
#define STEERING_PIN 7
void setup() {
Serial.begin(115200);
wheel.attach(WHEEL_PIN);
pinMode(THROTTLE_PIN, INPUT);
pinMode(STEERING_PIN, INPUT);
pinMode(MFORWARD_PIN, OUTPUT);
pinMode(MBACKWARD_PIN, OUTPUT);
//TCCR1B = TCCR1B & 0b11111000 | 0x01;
//TCCR2B = TCCR2B & 0b11111000 | 0x01;
}
void loop() {
int throttle = read_throttle();
int steering = read_steering();
delay (5);
throttle_handle(throttle);
steering_handle(steering);
}
// Read RX values
int read_throttle(){
int throttle = pulseIn(THROTTLE_PIN, HIGH, 20000);
throttle = map(throttle, 1000, 2000, -255, 255); //Substitute the high values to a value between -255 and 255.
constrain (throttle, -255, 255); //Make sure that the value stays within the desired boundaries.
//Serial.println(throttle);
}
int read_steering() {
int steering = pulseIn(STEERING_PIN, HIGH, 20000);
steering = map(steering, 1000, 2000, 24, 169); //Servo values, calibrated according to my steering servo.
constrain (steering, 24, 169); //Make sure that the value stays within the disired boundaries.
//Serial.println("steering");
}
void move_forward(int val) {
analogWrite (MFORWARD_PIN, val);
digitalWrite (MBACKWARD_PIN, LOW);
Serial.print(" vooruit: ");
Serial.print(val);
}
void move_backward(int val)
{
val = abs(val);
analogWrite (MBACKWARD_PIN, val);
digitalWrite (MFORWARD_PIN, LOW);
Serial.print(" achteruit: ");
Serial.print(val);
}
void move_stop()
{
digitalWrite (MFORWARD_PIN, LOW);
digitalWrite (MBACKWARD_PIN, LOW);
}
void throttle_handle(int throttle) {
//Serial.print("throttle");
if (throttle > 40) {
move_forward(throttle);
}
if (throttle < -40) {
move_backward(throttle);
}
else {
move_stop();
}
}
void steering_handle(int steering) {
wheel.write(steering);
// Serial.println("steering:");
// Serial.print(steering);
}
Unused index:
Everywhere you loop over three values, whereas you only use two items in the array. So you'd better change all your sizes to 2 instead of 3, or you can define a NB_INPUT constant at the top of your source code, that you can change easily for more flexibility:
#define NB_INPUT 2
...
for (int i = 0; i<NB_INPUT; ++i) {
...
RXOK in setup():
your comment about arrays is justified, the first bug I can see in your code is that you read from the RXOK array, whereas you did not put any values in it. If you're sure that RXSG gets only zeroes from pulseIn() on the first pass of the Read RX values loop it can be ok, but I doubt it is. e.g.:
for (int i=0; i<3; ++i)
RXOK[i] = 0;
So you should put values in RXOK values in setup().
constant indexes in a for loop:
Then you map() the values from 1000->2000 to -255->255 for RXSG[0] and RXSG[1] inside the for loop, which will be done for the three iterations. I'm not sure what you want there, but if you want to do it for constant indexes, you'd better do it outside of the loop. But as you're checking a constraint on the -255->255 domain for each value of the iteration loop, I think you may want to do it on relative values:
PWMSG[i] = map(RXSG[i], 1000, 2000, -255, 255);
but it seems the domain is dependent on the index, so you may want to make a couple of defines at the top of your source code:
#define THROTTLE_IDX 0
#define STEERING_IDX 1
and put your map() in a if statement:
if (i == THROTTLE_IDX)
PWMSG[i] = map(RXSG[i], 1000, 2000, -255, 255);
elif (i == STEERING_IDX)
PWMSG[i] = map(RXSG[i], 1000, 2000, 24, 169);
# add a else statement if you need to do a map for the other values of the array
constrain(PWMSG[i], -255, 255)
general algorithm
I'm not sure you really need an array for your use case. You'd better keep a few variables around and have a better use of functions for your code to be readable and less bugprone:
#define THROTTLE_PIN 6
#define STEERING_PIN 7
#define WHEEL_PIN 8
#define MFORWARD_PIN 13
#define MBACKWARD_PIN 10
Servo wheel;
// sets up the arduino
void setup() {
Serial.begin(115200);
wheel.attach(WHEEL_PIN);
pinMode(THROTTLE_PIN, INPUT);
pinMode(STEERING_PIN, INPUT);
}
// input data handling
int read_throttle() {
int throttle = pulseIn(THROTTLE_PIN, HIGH, 20000);
return map(throttle, 1000, 2000, -255, 255);
}
int read_steering() {
int steering = pulseIn(STEERING_PIN, HIGH, 20000);
return map(throttle, 1000, 2000, 24, 169);
}
// output actions handling
void move_forward(int val) {
analogWrite(MFORWARD_PIN, val);
digitalWrite(MBACKWARD_PIN, LOW);
// Serial.print...
}
void move_backward(int val) {
analogWrite(MFORWARD_PIN, val);
digitalWrite(MBACKWARD_PIN, LOW);
// Serial.print...
}
void stop_motor() {
digitalWrite(MFORWARD_PIN, LOW);
digitalWrite(MBACKWARD_PIN, LOW);
}
void handle_throttle(int throttle) {
if (throttle > 40)
move_forward(throttle);
elif (throttle < -40)
move_backward(throttle);
else
stop_motor();
}
// general algorithm
void loop() {
int throttle = read_throttle();
delay(5);
handle_throttle(throttle);
}
There are more code duplication, but sometimes it is better to duplicate code than to make a code almost unreadable, and hard to debug while not offering any kind of flexibility/modularity. And here are a few other things I found in your code that should be corrected:
Naming convention: try to use good names for your functions (two letters variables, or dutch variables are not a good idea, I'm not english native and I always avoid to use my own language based names in code even for code I don't share, you never know who will read your code in 2 days, 2 months, or 2 years).
globals: Try to avoid using global variables as much as possible. Declare only constant in the global scope : const int foo = 1; or preprocessor defines #define foo 1, so that you do not spend too much of the little RAM space you have on your arduino. The only exception to that rule, which is very specific to arduino development, are objects (like Servo in your code) that you need to declare globally so you can set them up in the setup() function, and use them in the loop() function.
If I extrapolate on what you've written, you may want to add a handle_steering() function such as:
void handle_steering(int steering) {
if (steering > NN)
turn_left(steering);
elif (steering < NN)
turn_right(steering);
else
keep_straight();
}
and change the loop() to :
void loop() {
int throttle = read_throttle();
int steering = read_steering();
delay(5);
handle_throttle(throttle);
handle_steering(steering);
}
To make it a more general case of handling dynamically and flexibly a number of features, you could keep a few arrays:
PIN[]: containing the pins,
DOM_MIN[]: containing the minimum of the features' domain (for the map),
DOM_MAX[]: containing the maximum of the features' domain (for the map),
BOUND_MIN[]: containing the minimum boundaries (for the handle_steering condition),
BOUND_MAX[]: containing the maximum boundaries (for the handle_steering condition),
ACTION[]: containing the pointers to functions.
and then your algorithm would look like:
int read_input(int i) {
int value = pulseIn(PIN[i], HIGH, 20000);
return map(value, 1000, 2000, DOM_MIN[i], DOM_MAX[i]);
}
int handle_action(int i, int value) {
if (value > BOUND_MIN[i])
*(ACTION[i])(value);
elif (value < BOUND_MAX[i])
*(ACTION[i])(value);
else
*(ACTION[i])(-1);
}
void loop() {
for (int i=0; i<NB_INPUTS; ++i) {
int value = read_input(i);
delay(5);
handle_action(i, value);
}
}
but as you're still not comfortable with arrays (and I assume pointers as well), I would not recommend going further that way for the time being. First do it simple and make it work and then you could try to factorize it following the idea I'm exposing here. But you're making a software that is embedded, where the RAM is rare and the processing power is low, while your code space is cheap. So it's one of the few occasions where you'd better want to make a more redundant code that will stay in program space, whereas you want to manipulate as little symbols in the RAM. That's why I'm not showing you how the arrays are being declared/defined, and how to handle function pointers, because I don't think that solution (where you were heading) is the right way to do what you want.
Always remember, simpler is better!
HTH