Global Variables in C Between Functions - c

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.

Related

Arduino Loop random amount of time

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);
}

Big latency in bluetooth communication

I have tried to write wireless servo control using two arduino nano v3 boards and two bluetooth 4.0 modules. First code is transmitter. It's very simple. It reads PPM signals and transform to separates PWM values for each channel. I use hardware serial port.
#include <PPMReader.h>
#include <InterruptHandler.h>
int ppmInputPin = 3;
int channelAmount = 2;
PPMReader ppm(ppmInputPin, channelAmount);
void setup()
{
Serial.begin(9600);
Serial.write("AT\r\n");
delay(10);
Serial.write("AT\r\n");
Serial.write("AT+INQ\r\n");
delay(5000);
Serial.write("AT+CONN1\r\n");
}
void loop()
{
unsigned long value1 = ppm.latestValidChannelValue(1, 0);
Serial.println(value1);
}
Receiver is simple too. It reads values from bluetooth and parse into integer value and sends to servo by 7th pin. Again I have used hardware serial port.
#include <Servo.h>
int PWM_OUTPUT = 7;
Servo servo;
void setup() {
servo.attach(PWM_OUTPUT);
Serial.begin(9600);
}
void loop() {
int pwmValue = Serial.parseInt();
if (Serial.available()) {
if(pwmValue > 900 && pwmValue < 2001) {
servo.writeMicroseconds(pwmValue);
}
}
}
All it works. But it has delay around 2-3 seconds. Can be problem in "spamming" serial port?
The first thing you need to ask yourself when implementing a device-to-device communication is how fast should I be sending? and if I send at that rate: is the receiver going to be able to keep pace (reading, doing processing or whatever it needs to do and answer back)?
This is obviously not about the baud rate but about what your loops are doing. You are using two different libraries: PPMReader and Servo. Now, pay attention to what each device is doing in their respective loops:
//Sending
void loop() {
unsigned long value1 = ppm.latestValidChannelValue(1, 0);
Serial.println(value1);
}
//Receiving
void loop() {
int pwmValue = Serial.parseInt();
if(pwmValue > 900 && pwmValue < 2001) {
servo.writeMicroseconds(pwmValue);
}
}
I don't really know how long it takes to execute each line of code (take a look here for some comments on that) but you cannot seriously expect both loops to magically synchronize themselves. Considering they are doing very different things (leaving out the serial part) dealing with different hardware, I would expect one of them to take significantly longer than the other. Think about what happens if that's the case.
As I said, I have no idea how long it takes to call ppm.latestValidChannelValue(1, 0) but for the sake of my argument let's say it takes 0.1 milliseconds. To have an estimate of the time it takes to complete one iteration around the loop you need to add the time it takes to print one (or two) bytes to the port with Serial.println(value1) but that's easier, maybe around 20-100 microseconds is a good ballpark figure. With these estimates, you end up reading 5000 times per second. If you are not happy or you don't trust my estimates I would suggest you do your own tests with a counter or a timer. If you do the same exercise for the other side of the link and let's say you get it's twice as fast, it runs 10000 times per second, how do you think it would happen with the communication? Yes, that's right: it will get clogged and run at snail pace.
Here you should carefully consider if you really need that many readings (you did not elaborate on what you're actually doing so I have no idea, but I lean on thinking you don't). If you don't, just add a delay on the sender's side to slow it down to a reasonable (maybe 10-20 iterations per second) speed.
There are other things to improve on your code: you should check you have received data in the buffer before reading it (not after). And you need to be careful with Serial.parseInt(), which sometimes leads to unexpected results but this answer is already too long and I don't want to extend it even more.
I found problem. It was in serial port spamming. I have added check if current value is not equal with previous value and it have started work and next small issue was in receiver. I read value before it was available.
#include <PPMReader.h>
#include <InterruptHandler.h>
int ppmInputPin = 3;
int channelAmount = 2;
PPMReader ppm(ppmInputPin, channelAmount);
volatile unsigned long previousValue1 = 0;
void setup()
{
Serial.begin(9600);
Serial.write("AT\r\n");
delay(10);
Serial.write("AT\r\n");
Serial.write("AT+INQ\r\n");
delay(5000);
Serial.write("AT+CONN1\r\n");
Serial.println("Transmitter started");
}
void loop()
{
unsigned long value1 = ppm.latestValidChannelValue(1, 0);
if(previousValue1 != value1) {
previousValue1 = value1;
Serial.println(value1);
}
}

Interrupt Handler behaving wierdly

I am using a code as shown. I have a buzzer connected to pin 14. The function 'Sound_Play()'(produces sound for 0.5 secs) does its work only when encountered the second time inside the loop.
void loop() {
inside_loop=1;
TCCR1A=0; //initialize Timer1 for 1sec duration
TCCR1B=0X0D;
OCR1A=15624;
TIMSK1=0X02;
Sound_Play(); //This does not seem to work
block1=1; block2=0;
while(timer1_value>0)
{digitalWrite(13,HIGH);}
block1=0; block2=1;
Sound_Play(); //This works
while(timer2_value>0)
{digitalWrite(13,LOW);}
timer1_value=time1_sec;
timer2_value=time2_sec;
}
ISR(TIMER1_COMPA_vect)
{ if (block1==1) {timer1_value--;}
else if (block2==1) {timer2_value--;}
}
void Sound_Play(){ //activate timer2 for producing sound for 0.5 secs
TCCR2B=0x07;
TCCR2A=0x02;
OCR2A=35;
TIMSK2=0x02;
counting=110;
}
ISR(TIMER2_COMPA_vect)
{ if(inside_loop)
{
if(counting>0){
digitalWrite(14,HIGH);
counting = counting-1;
}
else{
TIMSK2=0x00; //deactivate timer2 on completing the time
digitalWrite(14,0);
}}
I tried using function once inside loop . It still made buzzer on only when encountered second time. I don't think the priority of the interrupts must be causing this.
Can please someone explain why this function does not make sound on everytime it is encountered?
Thanks!
Bhuvnesh

AVR interrupt's variable updated in main

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);
}

Increasing an integer through a time delay

I'm producing a game in C on a microprocessor. The score is controlled by how long you can survive; the score increases by 1 every 3 seconds. The score is an integer which is declared globally, but displayed from a function.
int score = 0;//globally declared
void draw_score(int score_d)
{
char score_draw[99];
sprintf(score_draw,"%d", score_d);
draw_string(score_draw, 9, 0);
}
I was thinking of a function which just increases the score by one with a delay on it, however that has not worked.
void score_increaser(int score)
{
score++;
_delay_ms( 3000 );
}
Does it need to be in a while loop? the function itself would go into a while loop in the main anyway.
C is pass by value.
score_increaser() as shown in your question increases just a copy of what is passed in.
To fix this there are (mainly) two options:
As score is defined globally, do not pass in anything:
void score_increaser(void) {
score++;
_delay_ms( 3000 );
}
This modifes the globale score directly.
Pass in the address of score and de-reference it inside the function
void score_increaser(int * pscore) {
(*pscore)++;
_delay_ms( 3000 );
}
Call it like this
...
score_increaser(&score);
...
A 3rd, a bit more complex, approach (which assumes signals are supported on the target platform) would
setup a signal and a referring handler, then
setup a timer to fire a signal every N seconds.
This signal then is handled by the handler, which in turn
increases the global score and
starts the timer again.
This might look like:
#include <signal.h> /* for signal() and sig_atomic_t */
#include <unistd.h> /* for alarm() */
#define DURATION (3) /* Increase score every 3 seconds. */
sig_atomic_t score = 0;
void set_alarm(unsigned);
void handler_alarm(int sig)
{
++score;
set_alarm(DURATION);
}
void set_alarm(unsigned duration)
{
signal(SIGALRM, handler_alarm);
alarm(duration);
}
int main(void)
{
set_alarm(DURATION);
... /* The game's codes here. */
}
This latter approach has the advantage that your game's code does not need to take care about increasing score. score is just increased every 3 seconds as long as the program runs.
I'd recommend using a timer interrupt. Configure the timer to 3 seconds.
volatile int score = 0; //global
void Intr_Init(peripheral_t per)
{
//Initialize the timer interrupt
}
void draw_score(int score_d)
{
char score_draw[99];
sprintf(score_draw,"%d", score_d);
draw_string(score_draw, 9, 0);
}
int main(void)
{
Intr_Init(TIMER);
while(1)
{
//Code that makes your game run
draw_score(score);
}
}
ISR (TIMER1_COMPA_vect)
{
//clear disable interrupt
score++;
//enable interrupt
}
In embedded, you should rely on Timers for better time critical tasks and accuracy. The way Delay routines are implemented is usually a loop or a up/down counter. Whereas a timer is usually based on counting SysTicks.
Another major advantage of Interrupts is that you let processor do its tasks all the while instead of making it block in a delay loop.
score is global value then do not need to pass it in function if that function has access to that global space
void score_increaser() {
score++;
_delay_ms( 3000 );
}
here is a good method for handling the score.
in the 'start game' function,
clear 'score' to 0
setup a timer:
--to expire once each 3 seconds
--enable the automatic reload feature,
--enable the timer interrupt
--enable the timer counter
in the timer interrupt handler function
--increment 'score'
--clear the timer interrupt pending flag
in the 'end game' function
disable the timer counter
disable the timer interrupt
display the 'score' value
You dont need parameter for the score since it's declared globally..
//global
int score = 0;
void score_increaser()
{
_delay_ms(3000);
score++;
}
calling is like: score_increaser(); should do the work..
i suggest you check for score in any other line/function.. maybe you have redeclared it or accidentally changed the value..
hope this helped..

Resources