Arduino loop stops after for loop in called function - arduino

I am trying to make a radio controlled car which reacts to the frequency of music. The Loop works as it should and it gives me the correct frequency. The function berekenGrootte works too. This gives me the size of the frequency (max frequency - min frequency). But as soon as I want to use the function verdeel() which divides the size of the frequency in 10 to make the car move smoother it does it one or two times and then I don't get any feedback anymore in my serial monitor. Do I use too much Serial.print or do I need to restart the loop after the for loop in the second function?
#include <FreqMeasure.h>
void setup()
{
Serial.begin(57600);
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(2, OUTPUT);
pinMode(4, OUTPUT);
FreqMeasure.begin();
}
double sum = 0;
int count = 0;
float lowest = 50;
float highest = 0;
float grootte = 50;
float b[9][1];
void loop()
{
if (FreqMeasure.available()) {
// average several reading together
sum = sum + FreqMeasure.read();
count = count + 1;
if (count > 30) {
float frequency = FreqMeasure.countToFrequency(sum / count);
Serial.println(frequency);
sum = 0;
count = 0;
if (frequency < lowest) {
lowest = frequency;
Serial.print("new lowest: ");
Serial.println(lowest);
berekenGrootte();
}
else if (frequency > highest) {
highest = frequency;
Serial.print("new highest: ");
Serial.println(highest);
berekenGrootte();
}
/*if(frequency > 1000){
digitalWrite(3,HIGH);
delay(1000);
digitalWrite(3,LOW);
}
else{
digitalWrite(5,HIGH);
delay(1000);
digitalWrite(5,LOW);
}*/
}
}
}
void berekenGrootte()
{
grootte = highest - lowest;
Serial.print("new grootte: ");
Serial.println(grootte);
verdeel();
}
void verdeel()
{
float plength = grootte / 10;
b[0][0] = lowest;
b[0][1] = lowest + plength;
Serial.print("low: ");
Serial.println(b[0][0]);
Serial.print("high: ");
Serial.println(b[0][1]);
float startvalue = lowest + plength;
for (int i = 1; i < 10; i++) {
b[i][0] = startvalue;
b[i][1] = startvalue + plength;
startvalue = startvalue + plength;
Serial.print(i);
Serial.print(" low: ");
Serial.println(b[i][0]);
Serial.print(i);
Serial.print(" high: ");
Serial.println(b[i][1]);
}
}

You're overstepping the bounds of your b array.
float b[9][1];
The array is only 9 * 1.
void verdeel()
{
float plength = grootte / 10;
b[0][0] = lowest;
b[0][1] = lowest + plength;
So there is no element b[0][1]. The second number can only go up to 0 since the array is size 1 in that dimension. An array of size 1 is pretty useless as an array.
You have the same problem here in this loop at the end of that function:
for (int i = 1; i < 10; i++) {
b[i][0] = startvalue;
b[i][1] = startvalue + plength;
This for loop allows i to go to 9 which is too large for the array.

Related

Doppler radar (HB100) Arduino code : Why do we use bit-shifting?

I've been working on my doppler radar speed project for a while. I found this very helpful link and the code below:
// Based on the Adafruit Trinket Sound-Reactive LED Color Organ
// http://learn.adafruit.com/trinket-sound-reactive-led-color-organ/code
#define RADAR A5 // RADAR inut is attached to A7
#define MICRODELAY 100 // 100microseconds ~10000hz
#define MAXINDEX 1024 // 10 bits
#define TOPINDEX 1023 // 10 bits
byte collect[MAXINDEX];
int mean;
int minimum;
int maximum;
int hysteresis; // 1/16 of max-min
bool currentphase; // are value above mean + hysteresis;
int lastnull; // index for last null passing value
int prevnull; // index for previous null passing value
int deltaindex;
int deltadeltaindex;
int index;
bool phasechange = false;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
while (!Serial) {}
index = 0;
mean = 0;
maximum = 255;
minimum = 0;
hysteresis = 0;
currentphase = false;
lastnull = 0;
prevnull = 0;
Serial.print("deltadeltaindex");
Serial.print("\t");
Serial.print("deltaindex");
Serial.print("\t");
Serial.println("delta");
}
void loop() {
int newVal = analogRead(RADAR); // Raw reading from amplified radar
mean -= (collect[index] >> 2);
mean += (newVal >> 2);
collect[index]= newVal;
minimum = newVal < minimum ? newVal : minimum + 1;
maximum = newVal > maximum ? newVal : maximum - 1;
hysteresis = abs(maximum - minimum) >> 5;
if(newVal > (mean + hysteresis))
{
if(false == currentphase)
{
currentphase = true;
phasechange = true;
}
}
else if(newVal < (mean - hysteresis))
{
if(currentphase)
{
currentphase = false;
phasechange = true;
}
}
if(phasechange)
{
prevnull = lastnull;
lastnull = index;
int delta = (prevnull > lastnull) ?
(lastnull - prevnull + MAXINDEX) :
(lastnull - prevnull);
deltadeltaindex = abs(deltaindex - delta);
deltaindex = delta;
Serial.print(deltadeltaindex);
Serial.print("\t");
Serial.print(deltaindex);
Serial.print("\t");
Serial.println(delta);
}
index = index == TOPINDEX ? 0 : index + 1;
phasechange = false;
//delayMicroseconds(10);
}
I tried it out on my Arduino with HB100(model with breakout board), and it works just fine.
However, what I really wanted to do was to understand the mechanism behind the code. I read some articles on hysteresis and bit-shifting, but I simply cannot understand why the programmer here used bit-shifting.
What would mean -= (collect[index] >> 2); and mean += (newVal >> 2); do to the values exactly?
Help will be appreciated.

Arduino Wheel Speed Sensor Detect Direction

I'm trying to develop a wheel counter that determines both rotation rate, and the direction of rotation.
I have two magnetic pickup sensors mounted close together, and two metal chunks on the wheel 180 degrees apart.
Currently I have been able to measure rotation rate and convert this to distance, and the distance shown looks good. Here is the code for that:
volatile byte half_revolutions;
volatile byte half_revolutions_b;
volatile unsigned long last_time_a;
volatile unsigned long last_time_b;
volatile byte dir;
unsigned int rpm;
unsigned int rpm_b;
unsigned long timeold;
unsigned long timeold_b;
unsigned long time_print;
double distance = 0.0;
void setup()
{
Serial.begin(9600);
attachInterrupt(0, rpm_fun, RISING);
attachInterrupt(1, rpm_fun_b, RISING);
half_revolutions = 0;
half_revolutions_b = 0;
rpm = 0;
timeold = 0;
timeold_b = 0;
time_print = 0;
dir = 1;
}
void loop()
{
int rpm_guess;
if (half_revolutions >= 2)
{
rpm = 30*1000/(millis() - timeold)*half_revolutions;
timeold = millis();
half_revolutions = 0;
}
else if (millis() - timeold > 1000)
{
rpm = 0;
}
if (half_revolutions_b >= 2)
{
rpm_b = 30*1000/(millis() - timeold_b)*half_revolutions_b;
timeold_b = millis();
half_revolutions_b = 0;
}
else if (millis() - timeold_b > 1000)
{
rpm_b = 0;
}
if (millis() - time_print > 500)
{
rpm_guess = ((int)rpm + (int)rpm_b) / 2.0;
double rad_per_sec = (6.0*3.14159* rpm_guess)/180.0;
double metres_per_sec = rad_per_sec*0.038;
distance += metres_per_sec * 0.5;
Serial.print((int)last_time_b - (int)last_time_a);
Serial.print(",");
Serial.println(distance);
time_print = millis();
}
}
void rpm_fun()
{
half_revolutions++;
last_time_a = micros();
//Each rotation, this interrupt function is run twice
}
void rpm_fun_b()
{
half_revolutions_b++;
last_time_b = micros();
//Each rotation, this interrupt function is run twice
}
I was hoping to use the fact that sensor A should lead sensor B if rotation is clockwise, and vice-versa if anti-clockwise. However my logic doesn't seem to be working properly, Serial.print((int)last_time_b - (int)last_time_a); seems to switch between positive and negative no matter the direction I'm travelling.
I'd really appreciated any help with this.
I would rather do the direction guess in the interrupt handler:
void rpm_fun() {
if (last_time_a > last_time_b) dir = 0;
else dir = 1;
half_revolutions++;
last_time_a = micros();
}
void rpm_fun_b() {
if (last_time_a > last_time_b) dir = 0;
else dir = 1;
half_revolutions_b++;
last_time_b = micros();
}
If you experience "bounces", you could add some "debouncing" code.

Transition between two Steppers with independently assigned cues

I am going to use two step motors, two easy-drivers, one arduino uno.
Each step motors have gear to rotate, front and back.
First, I'd like to assign multiple rotation cues for each steppers. such as,
int step1cue1 = 329
int step1cue2 = 582
int step1cue3 = 1038
int step1 cue4 = 1790
...
int step2cue1 = 568
int step2cue2 = 1004
int step2cue3 = 1928
int step2cue4 = 3592
...
and each stepper needs minimum 0 and maximum value, such as,
int step1maxcue = 8372
int step2maxcue = 8421
each rotation speed and acceleration need to be set and controllable as well.
I would like to use rotation speed = 0 to make the stepper stopped at the cue.
** Operation
Both steppers start from 0,
First, stepper1 rotates to randomly chosen cue from its step1cues, when it almost reaches to the chosen cue, stepper2 starts to rotate to randomly chosen cue from step2cues.(stepper1 stopped at the cue with speed=0), when step2 almost reaches to its cue, stepper1 starts to rotate to another randomly chosen step1cue (not the current cue).. (stepper2 stops with speed=0).. and repeat this transition between two steppers.
Could you please help me with this code?
I would like to use the code from this,
#include <AccelStepper.h>
// Define two steppers and the pins they will use
AccelStepper stepper1(1, 9, 8);
AccelStepper stepper2(1, 7, 6);
int pos1 = 3600;
int pos2 = 5678;
void setup()
{
stepper1.setMaxSpeed(3000);
stepper1.setAcceleration(1000);
stepper2.setMaxSpeed(2000);
stepper2.setAcceleration(800);
}
void loop()
{
if (stepper1.distanceToGo() == 0)
{
pos1 = -pos1;
stepper1.moveTo(pos1);
}
if (stepper2.distanceToGo() == 0)
{
pos2 = -pos2;
stepper2.moveTo(pos2);
}
stepper1.run();
stepper2.run();
}
I don't know the AccelStepper library, so I can be wrong, but this should do what you requested:
#include <AccelStepper.h>
// With matrices it's easier
const int step1cues[] = { 329, 582, 1038, 1790 ...};
const int step2cues[] = { 568, 1004, 1928, 3592 ...};
// Define two steppers and the pins they will use
AccelStepper stepper1(1, 9, 8);
AccelStepper stepper2(1, 7, 6);
byte movingStepper;
// Distance from position when the motor should start
#define THRESHOLD 20
void setup()
{
// A0 should be disconnected. If it is used
// change this to an unused analog pin
randomSeed(analogRead(0));
stepper1.setMaxSpeed(3000);
stepper1.setAcceleration(1000);
stepper2.setMaxSpeed(3000);
stepper2.setAcceleration(1000);
// Make sure that steppers are at zero
stepper1.setCurrentPosition(0);
stepper2.setCurrentPosition(0);
// Pretend that we were moving motor 2
// It is already at position, so first
// loop will move motor 1 to a new position
movingStepper = 2;
}
void loop()
{
if (movingStepper == 1)
{
if (abs(stepper1.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step2cues[random(sizeof(step2cues)/sizeof(int))];
} while (abs(nextpos - stepper2.targetPosition()) < THRESHOLD);
stepper2.moveTo(nextpos);
movingStepper = 2;
}
}
else
{
if (abs(stepper2.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step1cues[random(sizeof(step1cues)/sizeof(int))];
} while (abs(nextpos - stepper1.targetPosition()) < THRESHOLD);
stepper1.moveTo(nextpos);
movingStepper = 1;
}
}
stepper1.run();
stepper2.run();
}
THRESHOLD is the "almost" in your sentence: when it is nearer than this value it will start moving the other motor. Note: the cues should be mode distant one from the other than twice the threshold value, so you won't have mixed conditions (I mean with that threshold the minimum distance from one cue and ANY other should be 40).
And by the way, you don't need to set speed to 0: when the stepper reaches the position it will halt by itself.
EDIT:
The OP asked three more features (print the next cue when chosen, print on serial the current position, set a switch when the motor reaches the cue), so here they are.
First of all I'd separate the second and third feature from the previous code, for clarity reasons. I chose to run that code only when the position changes, but this can easily be changed to
print that code only after a fixed amount of change (e.g. only after a change of 50 or more)
print that code at fixed amount of time (e.g. 0.5 s)
Anyway, here is the code:
int currentPos1 = -1;
int currentPos2 = -1;
void loop()
{
if (movingStepper == 1)
{
if (abs(stepper1.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step2cues[random(sizeof(step2cues)/sizeof(int))];
} while (abs(nextpos - stepper2.targetPosition()) < THRESHOLD);
stepper2.moveTo(nextpos);
Serial.print("Next cue for motor 2: ");
Serial.println(nextpos);
movingStepper = 2;
}
}
else
{
if (abs(stepper2.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step1cues[random(sizeof(step1cues)/sizeof(int))];
} while (abs(nextpos - stepper1.targetPosition()) < THRESHOLD);
stepper1.moveTo(nextpos);
Serial.print("Next cue for motor 1: ");
Serial.println(nextpos);
movingStepper = 1;
}
}
if (currentPos1 != stepper1.currentPosition())
{ // Stepper 1 has moved
currentPos1 = stepper1.currentPosition()
if (stepper1.distanceToGo() == 0)
{ // Stepper 1 has reached the final position
digitalWrite(switch1, HIGH);
}
else
{
digitalWrite(switch1, LOW);
}
Serial.print("Motor 1 pos: ");
Serial.println(currentPos1);
}
if (currentPos2 != stepper2.currentPosition())
{ // Stepper 2 has moved
currentPos2 = stepper2.currentPosition()
if (stepper2.distanceToGo() == 0)
{ // Stepper 2 has reached the final position
digitalWrite(switch2, HIGH);
}
else
{
digitalWrite(switch2, LOW);
}
Serial.print("Motor 2 pos: ");
Serial.println(currentPos2);
}
stepper1.run();
stepper2.run();
}
If you choose to modify it in order not to receive frequent motor updates (e.g. by showing the message every half a second) you should move the Stepper X has reached the final position block outside the control, so that it can be executed every iteration:
unsigned long lastShownMessages = 0;
void loop()
{
if (movingStepper == 1)
{
if (abs(stepper1.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step2cues[random(sizeof(step2cues)/sizeof(int))];
} while (abs(nextpos - stepper2.targetPosition()) < THRESHOLD);
stepper2.moveTo(nextpos);
Serial.print("Next cue for motor 2: ");
Serial.println(nextpos);
movingStepper = 2;
}
}
else
{
if (abs(stepper2.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step1cues[random(sizeof(step1cues)/sizeof(int))];
} while (abs(nextpos - stepper1.targetPosition()) < THRESHOLD);
stepper1.moveTo(nextpos);
Serial.print("Next cue for motor 1: ");
Serial.println(nextpos);
movingStepper = 1;
}
}
if ((millis() - lastShownMessages) > 500)
{ // More than 500 ms passed since last update:
Serial.print("Motor 1 pos: ");
Serial.println(stepper1.currentPosition());
Serial.print("Motor 2 pos: ");
Serial.println(stepper2.currentPosition());
lastShownMessages += 500;
}
if (stepper1.distanceToGo() == 0)
{ // Stepper 1 has reached the final position
digitalWrite(switch1, HIGH);
}
else
{
digitalWrite(switch1, LOW);
}
if (stepper2.distanceToGo() == 0)
{ // Stepper 2 has reached the final position
digitalWrite(switch2, HIGH);
}
else
{
digitalWrite(switch2, LOW);
}
stepper1.run();
stepper2.run();
}
PLUS, for a calibration purpose, can I see the rotation value (increment) of the stepper on the Server Monitor ? I can set the speed really low and let it roll, then I could know cue values for the stepcues that I need to set.
#include <AccelStepper.h>
// With matrices it's easier
const int step1cues[] = {10000 , 20000, 30000 , 40000 , 50000, 60000, 70000, 80000};
const int step2cues[] = {10000 , 20000, 30000 , 40000 , 50000, 60000, 70000, 80000};
// Define two steppers and the pins they will use
AccelStepper stepper1(1, 4, 3);
AccelStepper stepper2(1, 7, 6);
int switch1 = 12;
int switch2 = 13;
byte movingStepper;
// Distance from position when the motor should start
#define THRESHOLD 20
void setup()
{
Serial.begin(9600);
pinMode(switch1, OUTPUT);
pinMode(switch2, OUTPUT);
// A0 should be disconnected. If it is used
// change this to an unused analog pin
randomSeed(analogRead(0));
stepper1.setMaxSpeed(3000);
stepper1.setAcceleration(1000);
stepper2.setMaxSpeed(3000);
stepper2.setAcceleration(1000);
// Make sure that steppers are at zero
stepper1.setCurrentPosition(0);
stepper2.setCurrentPosition(0);
// Pretend that we were moving motor 2
// It is already at position, so first
// loop will move motor 1 to a new position
movingStepper = 2;
}
void loop()
{
if (movingStepper == 1)
{
if (abs(stepper1.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step2cues[random(sizeof(step2cues)/sizeof(int))];
} while (abs(nextpos - stepper2.targetPosition()) < THRESHOLD);
stepper2.moveTo(nextpos);
Serial.println("2");
Serial.println(nextpos);
movingStepper = 2;
if ( nextpos = stepper2.targetPosition() ){
digitalWrite(switch1, HIGH);
}
else {
digitalWrite(switch1, LOW);
}
}
}
else
{
if (abs(stepper2.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step1cues[random(sizeof(step1cues)/sizeof(int))];
} while (abs(nextpos - stepper1.targetPosition()) < THRESHOLD);
stepper1.moveTo(nextpos);
Serial.println("1");
Serial.println(nextpos);
movingStepper = 1;
if ( nextpos = stepper1.targetPosition() ){
digitalWrite(switch2, HIGH);
}
else {
digitalWrite(switch2, LOW);
}
}
}
stepper1.run();
stepper2.run();
}

Unexpected behavior in my RGB-strip driver code

I'm getting wrong output on the pins 9, 10 and 11. They are meant to be inputs for my RGB strip driver circuit. Which is basically an array of NPN transistors pulling current from the strip.
The basic idea is to get only 2 controls to set R, G, B and brightness. I'm using a button and a potenciometer. Potenciometer is used to set the value and the button to skip to next value setting. There is one setting state which is like the default one. It is the one to set the brightness and I will be using this most of the time. The othe ones are for setting the colors and when in one of those setting the strip will be blinking in between only the color I'm currently setting and the result with alle three colors set. The whole code was working just fine until I added the brightness setting and I think that I am kinda lost in my own code.
I even added a serial to read the outputs but I don't understand why are the numbers the way they are :(
int pinR = 9;
int pinG = 10;
int pinB = 11;
int potPin = A0;
const int buttonPin = 2;
int brightR = 0;
int brightG = 0;
int brightB = 0;
int brightness = 50; //
int R;
int G;
int B;
int potValue = 0;
int blinky = 0;
boolean blinking = false;
int buttonState;
int lastButtonState = LOW;
long lastDebounceTime = 0;
long debounceDelay = 50;
int setting = 0; //0=R 1=G 2=B 3=Brightness
void setup() {
// put your setup code here, to run once:
pinMode(pinR, OUTPUT);
pinMode(pinG, OUTPUT);
pinMode(pinB, OUTPUT);
Serial.begin(9600);
}
void RGBset(int r, int g, int b){
analogWrite(pinR, r);
analogWrite(pinG, g);
analogWrite(pinB, b);
}
void loop() {
// put your main code here, to run repeatedly:
potValue = analogRead(potPin);
potValue = map(potValue, 0, 1023, 0, 255); //read pot --> map to values from 0 - 255
int reading = digitalRead(buttonPin);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == HIGH) {
setting++;
}
}
}
lastButtonState = reading;
if(setting > 3){ // 0=R 1=G 2=B 3=Brightness
setting = 0; // cant get 4 cause there is no 4
}
if(setting == 0){
brightR = potValue;
if(blinking){
RGBset(brightR, brightG, brightB);
}else{
RGBset(brightR, 0, 0);
}
}
if(setting == 1){
brightG = potValue;
if(blinking){
RGBset(brightR, brightG, brightB);
}else{
RGBset(0, brightG, 0);
}
}
if(setting == 2){
brightB = potValue;
if(blinking){
RGBset(brightR, brightG, brightB);
}else{
RGBset(0, 0, brightB);
}
}
if(setting == 3){
brightness = potValue;
brightness = map(brightness, 0, 255, 1, 100); //mapping brightness to values from 1 - 100
R = brightR * brightness / 100; //set value * brightness / 100
G = brightG * brightness / 100; //that leads to get % of set value
B = brightB * brightness / 100; //255 * 50 / 100 = 127,5 ==> 128
RGBset(R, G, B); //it wont blink in thiss setting
}
if(setting != 3){
blinky++;
if(blinky > 1000){
blinking = !blinking;
blinky = 0;
}
}
String output = (String(brightR) + " " + String(R) + " " + String(brightG) + " " + String(G) + " " + String(brightB) + " " + String(B) + " " + String(brightness) + " " + String(potValue) + " " + String(blinking));
Serial.println(output);
delay(1);
}
First, in setup:
pinMode(buttonPin , INPUT);
Second, what are you expected when setting==3? You aren't reloading/updating the variables for brightR brightG brightB. So, when you change setting, you will lost the change of brightness

RGB Serial Issue

I am trying to make a Arduino program where it receives signals from the Serial monitor and then lights LED's accordingly, i have it set up with RGB. But I have a problem where all three LED's light like the blue one only should. here is my code:
#define SENSOR 0
#define R_LED 11
#define G_LED 10
#define B_LED 9
#define BUTTON 12
int val = 0;
int times = 0;
int btn = LOW;
int old_btn = LOW;
int state = 0;
int r = 0;
int g = 0;
int b = 0;
byte inByte = 0;
char buffer[5];
void setup() {
Serial.begin(9600);
pinMode(BUTTON, INPUT);
}
void loop() {
val = analogRead(SENSOR);
Serial.println(val);
if (Serial.available() > 0) {
inByte = Serial.read();
if (inByte == '#') {
r = Serial.read() + 1;
r = r * 25;
g = Serial.read() + 1;
g = g * 25;
b = Serial.read() + 1;
b = b * 25;
}
}
btn = digitalRead(BUTTON);
if ((btn == HIGH) && (old_btn == LOW)){
state = 1 - state;
}
old_btn = btn;
if (state == 1){
analogWrite(R_LED, r);
analogWrite(G_LED, g);
analogWrite(B_LED, b);
}else{
analogWrite(R_LED, 0);
analogWrite(G_LED, 0);
analogWrite(B_LED, 0);
}
delay(100);
}
Note: I am sure it is a coding issue, not a mechanical one,for your information.
If I understand what you're doing correctly, some code such as #987 will be sent on the serial monitor every time you want the color to change, correct? In that case, the issue is that when you do r = Serial.read() + 1; (and the same goes for b and g), Serial.read() is returning the ASCII code for a character from '0' through '9' (48 - 57). Try this:
r = Serial.read() - '0' + 1;
r = r * 25;
g = Serial.read() - '0' + 1;
g = g * 25;
b = Serial.read() - '0' + 1;
b = b * 25;
This will subtract the ASCII code for '0' first, so the numbers will be in the proper 0-9 range.
In your code, you're doing the identical thing to all three lights.
Why would you expect blue to behave differently?
analogWrite(R_LED, r);
analogWrite(G_LED, g);
analogWrite(B_LED, b);

Resources