Arduino Lily Pad mp3, Loop in Loop in Loop with timing - c++

the best way to explain my problem is in codeform.
const int ringerPin = A0;
const int offhook = A4;
const int onhook = A5;
void setup(){
pinMode(ringerPin, OUTPUT);
pinMode(offhook, INPUT);
pinMode(onhook, INPUT);
randomSeed(analogRead(0));
}
int randCall = random(60000, 3600000); // generate a random number between 1 min and 60 min
//ring every 1 to 60 minutes if the phone is down (hookon) and dont ring if the phone is picked up (no hookon)
void loop()
{
if (digitalRead(hookon) == HIGH)
void loop(){
delay(randCall);
//i dont know how to let this loop below here run for 30 seconds.
void loop()
{
//turn audio off - i dont know how to.
for(int x = 0; x < 15; x++){
digitalWrite(ringerPin, HIGH);
delay(50);
digitalWrite(ringerPin, LOW);
delay(80);
}
delay(2500);
}
else
//play one randomly choosen audiofile out of 10 - i dont know how to
}
}
I would be greatful if there is anybody who can give me some suggestions to my coding problems.?
I wrote them inside the code descriptions.

loop() is not a way to create a loop. loop() is the function that Arduino calls over and over when it can.
To create loops, use while or for. You can think of the loop() function as being the body of a while(true) loop.
That said, you should probably not use loops for what you are trying to do. There is a useful function called millis() that returns the number of milliseconds since the device was turned on. The value overflows every 50 days. You will need to handle that, but I suggest you write the loop() function to check if enough time has passed, and then do what it is supposed to. See this for an example.

Related

C++ buzzer to play piano notes for an Arduino

unsigned long t;
boolean isHigh;
#define BUZZER_PIN 3
void setup() {
// put your setup code here, to run once:
pinMode(BUZZER_PIN, OUTPUT);
isHigh = false;
t = micros();
}
void loop() {
playNote('c');
}
void playNote(char note) {
unsigned long timeToWait;
unsigned long timeToPlayTheNote = millis();
while (timeToPlayTheNote - millis() < 1000) {
if (note == 'c') {
timeToWait = 1911;
}
if (micros() - t > timeToWait) {
if (!isHigh) {
digitalWrite(BUZZER_PIN, HIGH);
isHigh = true;
} else {
digitalWrite(BUZZER_PIN, LOW);
isHigh = false;
}
t = micros();
}
}
}
I don't know why this won't work. I used to play a frequency every 1,000 microseconds but is there any way to make this simpler as well? Also, with this method I have to do (1/f)/2 and then convert that value from seconds to microseconds and use that as the value for timeToWait.
Initialization of ˋtimeToWait` should obviously be outside of the loop.
An array could be used for timing data.
ˋt` should probably be initialized inside ˋplayNoteˋ
Alternatively, you might use an enum for delay associated to a note.
enum class notes
{
C = 1911
};
Well, all suggestion assume that you don't want to compensate for drifting offsets.
Buzzers have a fixed frequency. They don't work like speakers at all. You will get better results with a real speaker. Don't forget to put a capacitor in series with it so the speaker sees an AC signal, you can fry a speaker quite easily if you feed it a DC signal..
For best results, you should use 2 x 47uF to 100uF electrolytic capacitors back to back, with the negative poles joined together, one positive to the 'duino and the other positive pole connected to the speaker. With higher capacitance, you'll get more bass.
Why don't you use a PWM at 50% (128) and change the PWM frequency to generate the sound? You could use the Timer1 or Timer3 library for that. Letting the hardware do the work would be more presise and would free your application for other tasks, such as reading a keyboard.
https://playground.arduino.cc/Code/Timer1
Setting the PWM at 0% with an analogWrite() would cut the sound.

For loop with if statement for ardiuno powered humidity control

Really simple question but I'm not entirely sure how to incorporate a for loop in the if statement I have. Context: I have a humidifier I am trying to automate based on the humidity of the room. I'm using an ardiuno, dht11 humidity sensor and a servo. The humidifier knob has three settings (high low off) and so the servo has three positions. I have the code running so the servo turns appropriately according to the humidity level. The issue is that it fluctuates very easily. To correct that I'm looking to incorporate a for loop so that after let say 60 one second iterations of the humidity being greater than 55 the servo moves. I tried to add a for loop but it doesn't seem to be working.
But this is only my solution based on the little programming I know. If there is a better solution or even an equally viable alternative I'd love to know. I'm currently studying mechanical engineering but I'm finding that to really make something one needs a background in electronics and code. I'm trying to learn both independently through a series of projects and so I'm quite eager to learn. Hopefully this helps explain why I'm asking such a simple questions to begin with.
#include <dht.h>
#include <Servo.h>
Servo myservo;//create servo object to control a servo
dht DHT;
#define DHT11_PIN 7 // pin for humidity sensor ( also measure temp)
void setup() {
myservo.attach(9);//attachs the servo on pin 9 to servo object
myservo.write(0);//statting off position at 0 degrees
delay(1000);//wait for a second
Serial.begin(9600);
}
void loop() {
int chk = DHT.read11(DHT11_PIN); // the follow is just so that I can see the readings come out properly
Serial.print("Temperature = ");
Serial.println(DHT.temperature);
Serial.print("Humidity = ");
Serial.println(DHT.humidity);
delay(500);
if (DHT.humidity > 55) // here is where my code really begins
{
for (int i=0; i>60; i++); // my goal is to execute the follow code after the statement above has been true for 60 one second iterations
{
myservo.write(0);//goes to off position
delay(1000);//wait for a second
}
} else if (DHT.humidity > 40 ) {
for (int i=0; i>60; i++); // same thing here
myservo.write(90);//goes to low position
delay(1000);//wait for a second
}
else
{
for (int i=0; i>60; i++);
myservo.write(180);//goes to high position
delay(1000);
}
} // end of void loop()
Just addressing your question, the following line is incorrect:
for (int i=0; i>60; i++);
Two things:
1) The second statement in the for loop describes the conditions on which it executes. The way it is written, it will only execute when i>60 (not what you want according to the comments).
2) The semicolon after the for statement makes the next block unassociated.
Correct that line to the following:
for (int i=0; i<60; i++)
See the following for more information:
https://www.tutorialspoint.com/cprogramming/c_for_loop.htm
It would probably be helpful to examine your compiler warnings, and/or set a higher warning level, to catch these type of things early (this is, of course, somewhat compiler dependent).
I guess you trying kind of de-bouncing at you need humid level stay in same range for some period.
First, I define conversion function to map humid level to state
#define HUMID_OFF 1
#define HUMID_LOW 2
#define HUMID_HIGH 3
byte state_conv (float humid_level){
if (humid_level > 55) return HUMID_OFF ;
else if (humid_level > 40 ) return HUMID_LOW ;
else return HUMID_HIGH ;
}
Second I will check changing of state and use millis() to count time while current state is steady. if counting time are longer than threshold then change the actual state.
/*Global variable*/
byte actual_state;
byte flag_state;
void setup (){
// Do things that necessary
float humid = dht.readHumidity();
/*Initialize value*/
actual_state = state_conv(humid);
flag_state= state_conv(humid);
}
void loop(){
static unsigned long timer = millis();
float humid = dht.readHumidity();
byte crr_state = state_conv(humid);
if (crr_state != actual_state ){// if state is changing
if (flag_state != crr_state){
/if crr_state change form last iteration then reset timer
flag_state = crr_state;/
timer = millis();
}
else if (millis() - timer > 10000){
//if crr_state not change for 10000 ms (10 second)
actual_state = crr_state; // update actual state to crr_state
}
}
// After this use actual_state to control servo
if (actual_state == HUMID_OFF ){
myservo.write(0);//goes to off position
}
else if (actual_state == HUMID_LOW ){
myservo.write(90);//goes to low position
}
else if (actual_state == HUMID_HIGH ){
myservo.write(180);//goes to high position
}
}
DHT.humidity returns a float, so if you want to compare, then first store this in an int, and then compare.

Arduino timed void draw() loops

I have an Arduino Uno set up to sense the light level and draw to a text file via Processing when it gets dark. I'd like to modify the Processing code to interrupt the draw loop for five seconds and then restart the draw loop. This will continuously write and overwrite the .txt file but that's not important right now.
The purpose of this excercise is to understand how to insert a break into the endless draw loop. I'm still very much a newbie to programming and am trying to wrap my head around how commands interact with eath other. Can anyone help me understand how to make this work? Eample code would be great but I'd also be happy with a conceptual description of how it's supposed to work...learn by doing and all.
I've tried putting the void draw() loop within a void loop() but it erred out. Am I on the right path?
<setup...mySerial and createWriter to path/file.txt>{
}
void draw() { //this is what needs to terminate & restart
if (mySerial.available() > 0 ) {
String value = mySerial.readString();
if ( value != null ) {
output.println( value );
}
}
}
void keyPressed and end
I believe what you're looking for is called a "state machine".
Make a variable that you can use to store a time value, then compare that to the current time to see if 5s have passed.
uint32_t last_trigger = 0; // millis() returns an unsigned, 32-bit integer
void setup()
{
Serial.begin(9600);
}
void loop()
{
if (millis() - last_trigger > 5000) { // 5000 milliseconds
last_trigger = millis(); // update last_trigger
Serial.print("last triggered at "); // report findings
Serial.print(last_trigger);
Serial.println(" milliseconds");
}
}
http://www.arduino.cc/en/Reference/Millis
If you aren't worried about really tight timing, the easy solution is to use the delay function. http://www.arduino.cc/en/Reference/Delay
The following might be a simple sketch that would do what you want. Adjust it as needed.
void setup()
{
Serial.begin(9600); // initialize serial routines
}
void loop()
{
int a = analogRead(0); // read the value of lightness
Serial.println(a); // tell processing what the value is
delay(5000); // wait for a 5 seconds
}

When to use a while loop or if statement?

Can you give some examples of situations where a while loop and a if loop would be appropriate?
I am working on this project where an Arduino reads an analog input from a variable resistor.
This is how I have it read the raw input:
int intputValue = analogRead(A0);
Then I convert the raw input into a number between 0 and 100 for percentage:
double percentValue = inputValue * (1.0/10.23);
So then I use this percentValue to determine whether the Arduino needs to send signal(s) through several of its digital pins. I have signals going to a 4 channel relay module. Basically my idea is that if the percentValue is between 0-25, one of the relays would turn on, hence only one digital pin would need to be activated. Between 26-50, two pins, 51-75, three pins, and 76-100, four pins.
Here's my question: Should I use a if statement:
if(percentValue >=0 && percentValue <=25){
digitalWrite(pin1, HIGH); //turns on pin 1
}
Or use a while loop:
while(percentValue >= 0 && percentValue <=25){
digitalWrite(pin1, HIGH); //turns on pin 1
}
Then I'm going to do a similar thing for the rest of the percentValue ranges.
Is there a difference between using "if" and "while" in this case?
Thanks for any help.
There should be a setup and loop function in your code, you can put if in your loop function.
void setup() {
// put your setup code here, to run once:
int intputValue = analogRead(A0);
}
void loop() {
// put your main code here, to run repeatedly:
double percentValue = inputValue * (1.0/10.23);
if(percentValue >= 0 && percentValue <= 25){
digitalWrite(pin1, HIGH); //turns on pin 1
}
}
While loops are used to run a specific code block as long as certain parameters are met. An if statement is similar but it will only run the said code block once but a while statement will run until told otherwise.
So effectively:
while(1 == 1)
{
System.out.println("Hello World");
}
Will print Hello World indefinitely. On the other hand:
if(1 == 1)
{
System.out.println("Hello World");
}
Will print Hello World once.
Just for fun since your understanding of loops is shady; a for loop will run a specified number of times:
for(int i = 0; i < 3; i++)
{
System.out.println("Hello World");
}
Would print Hello World 3 times.
refer to:
While loop
For loop
If statement
General Java Tutorials
"Then I'm going to do a similar thing for the rest of the percentValue ranges."
This implies you should use an if statement, and not a while loop, especially if you want to do anything else with the device.
Presumably, this code will be placed in the Arduino loop() function, which is called repeatedly, giving you a loop. You don't want the Arduino to get stuck in a while loop of your own.
It appears that you want to light up different LEDs depending on the reading. You will want to turn off the other LEDs in the body of your if statements as well. Otherwise, the Arduino will just eventually have all 4 LEDs lit up.
if(percentValue >=0 && percentValue <=25){
digitalWrite(pin1, HIGH); //turns on pin 1
digitalWrite(pin2, LOW);
digitalWrite(pin3, LOW);
digitalWrite(pin4, LOW);
}
// etc.

Calling constant complexity O(1) 5 line function significantly impacts performance, why?

I have the following code:
#include <ros.h>
#include <ros/time.h>
#include <sensor_msgs/Range.h>
#define sensNumber 3
#define firstTrigPin 3
#define firstEchoPin 9
ros::NodeHandle nh;
sensor_msgs::Range range_msg;
ros::Publisher pub_range( "/ultrasound", &range_msg);
char frameid[] = "/ultrasound";
int trigPin=firstTrigPin;
int echoPin=firstEchoPin;
void increasepins(){
trigPin++;
echoPin++;
if(trigPin>firstTrigPin+sensNumber){
trigPin=firstTrigPin;
}
if(echoPin>firstEchoPin+sensNumber){
echoPin=firstEchoPin;
}
}
void setup(){
nh.initNode();
nh.advertise(pub_range);
for(int i=0;i<sensNumber;i++){
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
increasepins();
}
range_msg.radiation_type = sensor_msgs::Range::ULTRASOUND;
range_msg.header.frame_id = frameid;
range_msg.field_of_view = 0.1;
range_msg.min_range = 0.0;
range_msg.max_range = 6.47;
}
long range_time;
void loop()
{
increasepins();
//publish the adc value every 50 milliseconds
//since it takes that long for the sensor to stablize
long duration, distance;
digitalWrite(trigPin, LOW); // should be high?
delayMicroseconds(2); // make this 20
digitalWrite(trigPin, HIGH);
delayMicroseconds(10); // reset value?
digitalWrite(trigPin, LOW);
distance = pulseIn(echoPin, HIGH)/ 58,2; //sensor constant is 3.4
range_msg.range = distance;
range_msg.header.stamp = nh.now();
range_time = millis() + 50;
range_msg.field_of_view = trigPin;
range_msg.min_range = echoPin;
pub_range.publish(&range_msg);
nh.spinOnce();
}
This above code runs at my funduino at aprox 2 times a second for the whole loop. If I however remove the increasePins method it runs at around 100 times per second. Why the big chance? It seems like such a trivial piece of code (just increase 2 variables and then compare them) make such a large difference?
For reference we are talking about this function:
void increasepins(){
trigPin++;
echoPin++;
if(trigPin>firstTrigPin+sensNumber){
trigPin=firstTrigPin;
}
if(echoPin>firstEchoPin+sensNumber){
echoPin=firstEchoPin;
}
}
Which to me looks really simple when compared to having to wait for the echo to come back and getting the time and that sort of things required for the rest of the code.
I believe that one of the problem is that if you comment the increasePins function in the loop, the compiler will decide to take some of the logic outside the loop. For that you need to look # the assembly code and see what's being done inside the loop.
Another problem may be related to the pin behavior. For example, I read that "pulseIn" function sends a pulse to the pin and measures it's duration. You use it to pulse the "echoPin". I suspect that if you don't change the echoPin you will have a rather constant duration. However, changing the echoPin may lead to a situation where another pin's pulse duration would be longer. To test this, you can try and use pulsePin(echoPin, HIGH, timeout) with a timeout parameter for the case when you did not comment the increasePins function. I expect the loop to run faster.
So i think that the increasePins is not a bottleneck. I recommend making it inline however (could add some speedup if the compiler hasn't done this already).