else if stops at first iteration [Arduino] - if-statement

My code stops at the first iteration for the phot_val "if" statement.
/////// Code loop
void loop() {
double sound = MIC(); //Declare variable for obtaining microphone data
double phot_val;
int nreadings = 100;
int song1[N]={CN4, DN4, EN4, FN4, GN4, AN4, BN4, CN5};
int song2[M]= {RT0, RT0, CN4, DN4, CN4, FN4, EN4, RT0,CN4, DN4, CN4, GN4, FN4, RT0, CN4, CN5, AN4, FN4, EN4,DN4, RT0, AS4, AN4, FN4, GN4, FN4, RT0, RT0};
phot_val = read_analogn(2,nreadings);
Serial.print("Sound: ");Serial.println(sound); //Testing purposes, Print out sound/mic value
Serial.print("Light: ");Serial.println(phot_val,5);//Testing purposes, Print out light sensor data
if(phot_val >= .5){play_song(song1,N);} //Stops after first 100???
/// Else If statements to change RBG colors depending on sound
if(MIC() >= 30){ setColor(255, 0, 0); } //Red Color
else if(MIC() >= 35){setColor(0, 255, 0);} //Green Color
else if(MIC() >= 40){setColor(0, 0 , 255);} //Blue Color
else if(MIC() >=25){setColor(255, 255, 255);} //White Color
else if(MIC() >=25){setColor(170, 0, 255);} //White Color
else {setColor(0, 0, 0);}
}
/////// Read light sensor function
float read_analogn(int p, int n){
float sum = 0;
float avg;
int i;
float voltage;
float phot_val;
for(i=0; i<n; i++)
{
phot_val = analogRead(p);
voltage = phot_val*(5.0/1023.0);
sum += voltage;
}
avg = sum/n;
return (avg);
}
/////// Color function for RBG Leds
void setColor(int redV, int greenV, int blueV) {
analogWrite(redP, redV); //Red value for RBG
analogWrite(greenP, greenV); //Green value for RBG
analogWrite(blueP, blueV); //Blue value for RBG
}
/////// Play song function
void play_song(int song[], int n){
int isong; //Define variables
for(isong=0;isong<n;isong++){ //For loop to play the songs
tone(SPKR,song[isong]);
delay(500);
}
noTone(SPKR);
}
}
I can post more code if needed, but I have no Idea why it stop
Edit: Fixed title, and added more code of the functions.
So basically it runs tru but when "if(phot_val >= .5){play_song(song1,N);}" becomes true it stops until the song it's played entirety then it continues to read data again.

You aren't checking the value of the analog pin in the for loop so it blocks everything until the entirety of the song finishes. All you need to do is update the for loop to check the value of the input.
Replace your for loop with something like:
for(isong=0;isong<n;isong++){
tone(SPKR,song[isong]);
delay(500);
phot_val = read_analogn(2, nreadings);
if(phot_val < .5){break;} //or whatever value you want it to stop at
}
This will stop the song when your sensor goes below the threshold

I do not see any for loop , perhaps read_analogn(); is a function you declared which contains a for loop?
In that case you should check the function in order to make sure the for loop does not fall into an infinite loop , perhaps place some serial outputs in different parts of the code to see if it reaches that part , print out variables to check if different parts of the code are operating and so on.
Nevertheless it is hard to say what is happening without seeing the for loop / function which is causing the trouble so I suggest you place the functions code and the for loop itself in your question.

The first else if in your code is at this questionable location:
if(MIC() >= 30){ setColor(255, 0, 0); } //Red Color
else if(MIC() >= 35) {
// comes here only if the first call of MIC() returns less than 30
// and the second one returns 35 or more.
// ???
}
This is not an answer, but hard to read as a comment.

Related

Arduino RGB LED random PWM Level

I am attempting to create a program that will randomly choose a PWM value for a RGB LED from a given Array. It works fine with the first color, blue. Bu then I nest in a second color, green, I loose the blue from displaying and only the green displays.
void loop() {
// put your main code here, to run repeatedly:
int x[9] = {0, 32, 64, 96, 128, 160, 192, 224, 256}; //setup Array X for brightness options
int blueVariable = 0; //Blue LED
int greenVariable = 0; //Green LED
for (int blueLed = 0; blueLed > -1; ) { //for loop to choose PWM option
analogWrite(11, x[blueVariable]); //Initilize the PWM function on pin 11 to brightness of blueVariable
// if (blueLed == 255) blueLed = 0; //
blueVariable = random(0,8); //Random function to decide on blueVariable value
delay(500);
for (int greenLed = 0; greenLed > -1; ) {
analogWrite(10, x[greenVariable]);
// if (g == 255) g = 0; // switch direction at peak
greenVariable = random(0,255);
delay(500);
}
}
}
You have two Problems:
First you hooked your "for loop" for the green color in(!) the for loop for the Blue color. Based on the fact that the loops running infinite you only loop through the second for loop.
The second Problem (perhaps not a problem, but the reason why you don't see Blue) is your initialization of the blueVariable as 0.
If you run the first time, you write the value 0 to the PWM Pin. After that you change the variable, but do not write to the PWM Pin, because you get stuck in your "infinite green Loop".
Btw, like said in the comments from Michael, you should change the 255 to 8 AND in your array you should change the last value (256) to 255 because the 8bit PWM means 256 values from 0-255.
Example:
int x[9] = {0, 32, 64, 96, 128, 160, 192, 224, 255}; // Changed Value
void loop() {
int blueVariable = 0; //Blue LED
int greenVariable = 0; //Green LED
while(1) { // Because it was infinite already i changed it to while(1)
blueVariable = random(0,8); //Put in front of analogWrite()
analogWrite(11, x[blueVariable]);
delay(500);
// Deleted the scond loop
greenVariable = random(0,8); // Value changed from 255 to 8; Also put in front of analogWrite
analogWrite(10, x[greenVariable]);
delay(500);
}
}

Stopping a program under certain conditions

I am greeting you today with a program question for my project that uses light as an input for a servo on a wall. Light will enter the room and the shade will go down, and in the absence of light, the shade will recede. I would like to make two conditions in a void loop in the arduino code only applicable one time unless the condition changes. By saying this I mean that, I want this void loop to run continually,in which i have two conditions. And if the same condition is met twice in a row,(ie. sensor reading between 800 and 10000, like 5000 and and then at 6032), nothing will run. If one condition is met and then the other is met afterwards, that's ok. Here's my code and any help as to what reference commands I should use or my next course of action would be greatly appreciated.
// Reports the frequency from the TSL230, higher number means brighter
// Part: http://www.sparkfun.com/products/8940
// Article: http://bildr.org/2011/08/tsl230r-arduino/
#include <Servo.h>
Servo myservo1;
int TSL230_Pin = 4; //TSL230 output
int TSL230_s0 = 3; //TSL230 sensitivity setting 1
int TSL230_s1 = 2; //TSL230 sensitivity setting 2
int TSL230_samples = 30; //higher = slower but more stable and accurate
void setup(){
Serial.begin(9600);
setupTSL230();
pinMode(5,OUTPUT);
}
void loop(){
float lightLevel = readTSL230(TSL230_samples);
Serial.println(lightLevel);
if(lightLevel>800 && lightLevel<1000)
{
myservo1.attach(5);
myservo1.writeMicroseconds(1300);delay(1000);
myservo1.writeMicroseconds(1500);delay(5000000);
}
else if(lightLevel<800)
{
myservo1.attach(5);
myservo1.writeMicroseconds(1700);delay(5000);
myservo1.writeMicroseconds(1500);delay(5000000);
}
}
void setupTSL230(){
pinMode(TSL230_s0, OUTPUT);
pinMode(TSL230_s1, OUTPUT);
//configure sensitivity - Can set to
//S1 LOW | S0 HIGH: low
//S1 HIGH | S0 LOW: med
//S1 HIGH | S0 HIGH: high
digitalWrite(TSL230_s1, LOW);
digitalWrite(TSL230_s0, HIGH);
}
float readTSL230(int samples){
//sample light, return reading in frequency
//higher number means brighter
float start = micros();
int readings = 0;
while(readings < samples){
pulseIn(TSL230_Pin, HIGH);
readings ++;
}
float length = micros() - start;
float freq = (1000000 / (length / samples)) * 10;
return freq;
}
First add this to your setup ...
void setup(){
Serial.begin(9600);
setupTSL230();
pinMode(5,OUTPUT);
myservo1.attach(5);
}
Then make a new variable and add it to your if statements
Boolean once; // declare this with your other int variables
if(lightLevel > 800 && lightLevel < 1000 && once==True)
{
myservo1.writeMicroseconds(1300);delay(1000);
myservo1.writeMicroseconds(1500);delay(1000);
once = False;
}
else if(lightLevel<800 && once == False)
{
myservo1.writeMicroseconds(1700);delay(5000);
myservo1.writeMicroseconds(1500);delay(1000);
once = True;
}

Chessboard in opengl

I'm trying to create 5x5 chessboard in OpenGL. I have been able to design a 5x6, and 8x8 but the code just won't work for the 5x5.
Can someone look over the code and maybe point out where my mistake is as the width just wont change to 5?
Here is the part of the code i seem to have a problem with:
void drawScene()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-2.5*1.5, 0.0, 2.5*1.5);
for(double j=0.0;j>(-5*1.5);j-=1.5)
{
k++;
for(i=0.0;i<(2.5*3.0);i+=3.0)
{
if(k%2!=0)
{
glPushMatrix();
glTranslatef(i,0.0,j);
glCallList(_displayListId_blackArea);
glPopMatrix();
}
else
{
glPushMatrix();
glTranslatef(i+1.5,0.0,j);
glCallList(_displayListId_blackArea);
glPopMatrix();
}
}
}
for(double j=0.0;j>(-5*1.5);j-=1.5)
{
k++;
for(i=0.0;i<(2.5*3.0);i+=3.0)
{
if(k%2!=0)
{
glPushMatrix();
glTranslatef(i,0.0,j);
glCallList(_displayListId_whiteArea);
glPopMatrix();
}
else
{
glPushMatrix();
glTranslatef(i+1.5,0.0,j);
glCallList(_displayListId_whiteArea);
glPopMatrix();
}
}
}
}
If you have an odd number of columns, your "odd vs. even" for black vs white will go different than if you have an even number. I think the easiest way is to do one loop for all the Squares, and keep a bool white_or_black variable that is set to white_or_black = !white_or_black at the end of each loop.
There is also a large amount of duplicated code that could be made much simpler by having one loop rather than two.
[I'm not 100% sure what is going wrong in your code, so I'm not sure if this will ACTUALLY fix the problem - but I believe it's a worthwhile improvement].
Understand your problem first. You have to draw odd vs even for black vs white board that means at first row if you draw odd white board then you have to draw even black board and in next row even white board and odd black board. For completing 5*5 chessboard pattern for white and black board row wise is given below:
3*2
2*3
3*2
2*3
3*2
But code you provide is for equal number of white and black board so you have to change the logic.Here is the part of code where I used my logic to draw 5*5 chessboard and its works perfectly.
for(float j=0.0;j>(-5*1.5);j-=1.5)
{
k++;
//for(i=0.0;i<(4*3.0);i+=3.0)
//{
if(k%2==0)
{
for(i=0.0;i<(3*3.0);i+=3.0){
glPushMatrix();
glTranslatef(i,0.0,j);
glCallList(_displayListId_blackArea);
glPopMatrix();
}
}
else
{
for(i=0.0;i<(2*3.0);i+=3.0){
glPushMatrix();
glTranslatef(i+1.5,0.0,j);
glCallList(_displayListId_blackArea);
glPopMatrix();
}
}
//}
}
k=0;
for(float j=0.0;j>(-5*1.5);j-=1.5)
{
k++;
//for(i=0.0;i<(4*3.0);i+=3.0)
//{
if(k%2!=0)
{
for(i=0.0;i<(3*3.0);i+=3.0){
glPushMatrix();
glTranslatef(i,0.0,j);
glCallList(_displayListId_whiteArea);
glPopMatrix();
}
}
else
{
for(i=0.0;i<(2*3.0);i+=3.0){
glPushMatrix();
glTranslatef(i+1.5,0.0,j);
glCallList(_displayListId_whiteArea);
glPopMatrix();
}
}
}
k=0;
glutSwapBuffers();
}
I suspect that by "the width won't change to 5", you are observing a width of 4 or 6. Would that be correct? It's quite likely in that case to be an error due to double-precision arithmetic.
You see, you assume infinite precision in your loops, but it's quite conceivable that 5*1.5 is not the same as adding 1.5 five times.
What you should really do is have an integer loop from 1 to 5 (or 0 to 4), and then multiply that value by your square size to produce a co-ordinate. It's generally not a good idea to loop over doubles unless you know what you are doing and what can happen.
Another thing that you should PLEASE do is use constants instead of literals. Instead of peppering your code with the number 5, why not define:
const int BoardWidth = 5;
const int BoardHeight = 5;
Then it will be a lot easier to change.
Forget that code, it has bad potential, you should use ints as a counter to create the board. For example:
const unsigned BOARD_SIZE = 5;
for(unsigned i = 0; i < BOARD_SIZE; ++i){
for(unsigned j = 0; j < BOARD_SIZE; ++j){
drawBoardCell(i,j, (i*BOARD_SIZE + j) % 2 == 0);
}
}
void drawBoardCell(const int row, const int col, const bool isBlack){
glPushMatrix();
glTranslatef(col+1.5,0.0,row);
const int callId = isBlack ? _displayListId_blackArea : _displayListId_whiteArea;
glCallList(callId);
glPopMatrix();
}
That might not work at first try but it should give you a starting point.

Strange issue trying fade on arduino on multiple LEDs

I am trying to test out Fade on multiple LEDs on an Arduino Uno. Here's the code i have written
int led[2] = {9,10}; // the pin that the LED is attached to
int brightness[2] = {0,0}; // how bright the LED is
int fadeAmount[2] = {5,15}; // how many points to fade the LED by
long previousMillis[2] = {0,0}; // will store last time LED was updated
long interval[2] = {30, 50};
// the setup routine runs once when you press reset:
void setup() {
// declare pin 9 to be an output:
pinMode(led[0], OUTPUT);
pinMode(led[1], OUTPUT);
Serial.begin(9600);
}
// the loop routine runs over and over again forever:
void loop() {
// set the brightness of pins:
for (int counter = 0; counter < 2; counter++) {
unsigned long currentMillis = millis();
analogWrite(led[counter], brightness[counter]);
Serial.print("LED ");
Serial.print(led[counter]);
Serial.print(": Brightness ");
Serial.println(brightness[counter]);
if (currentMillis - previousMillis[counter] > interval[counter]) {
// change the brightness for next time through the loop:
brightness[counter] = brightness[counter] + fadeAmount[counter];
// reverse the direction of the fading at the ends of the fade:
if (brightness[counter] == 0 || brightness[counter] == 255) {
fadeAmount[counter] = -fadeAmount[counter] ;
}
}
}
}
Here's the weird thing. If i comment out the Serial stuff (print and begin), the fades don't work. They just "flicker" a little.
Any idea what is wrong?
I figured it out. It looks like I forgot a line of code.
previousMillis[counter] = currentMillis;
I should have put that in on the first if statement in the code. I guess the act of observing by using the serial print slowed things down enough that the code seemed to work.
Boy, do i feel foolish.

How to change a color to random in OpenGL?

I've tried countless times to try and get this to work. I've moved loads of it around but still, nothing works. When I press the M key, my lights are meant to change to random colours. However, they change just to white.
This is what i have...
float colorArray[100][3]; // Create an array for random colors
keyPressed function:
case 'm' | 'M':
updateLights(2);
break;
defined_to_openGL function:
for (int i = 0; i < 3; i++)
{
glPushMatrix();
glColor3f(colorArray[i][0],colorArray[i][1],colorArray[i][2]);
glTranslatef(-50*i/2,-20,0.5); // Begin the first circle at -50, -20. Then multiply by i to create a space between them.
drawLights(2.0f);
glPopMatrix();
if(i <= 3)
{
glPushMatrix();
glColor3f(colorArray[i][0],colorArray[i][1],colorArray[i][2]);
glTranslatef(-38,-20,0.5);
drawLights(2.0f);
glPopMatrix();
glPushMatrix();
glColor3f(colorArray[i][0],colorArray[i][1],colorArray[i][2]);
glTranslatef(-12,-20,0.5);
drawLights(2.0f);
glPopMatrix();
}
}
Update lights function:
{
cout << "update lights" << endl;
for(int i = 0; i < 3; i++)
{
colorArray[i][0] = rand() % 255;
colorArray[i][1] = rand() % 255;
colorArray[i][2] = rand() % 255;
glutPostRedisplay();
}
}
You are using glColor3f which accepts 3 float parameters in [0.0,1.0] for each color intensity while rand()%255 produces an output which is in [0,254].
You can either switch to glColor3ub( GLubyte red, GLubyte green, GLubyte blue) which accepts an unsigned byte (and change modulo to %256 since you are skipping a value with 255) or generate a value in [0.0,1.0]by changing your random generation to
rand()/((float)RAND_MAX+1)
but this mean that you will have to change the type of colorArray to GLFloat.