How to add input values to arrays in C++? - c++

I am making a distance sensor that lights up a LED-Strip when something is near the sensor. I want to add the latest value measured to an array and make the LED-Strip turn off if none of the 20 latest values are more than 200 (a certain distance away from the sensor). Here is the code:
#define DO_Redled 14
int DO_RedLed = 14; //Output D5 (Red Led)
int AI_Pot= 0;
int PotValue = 0;
int brightness = 0;
void setup(){
Serial.begin(9600);
int values[20] = {};
}
void loop(){
PotValue = analogRead(AI_Pot);
analogWrite(DO_RedLed, PotValue);
Serial.println(PotValue);
delay(50);
}
I've tried some other code, but I didn't understand it and therefore couldn't adapt it to my own code. Any help?

You can simply create a counter and check if it reach 20
#define DO_Redled 14
int AI_Pot= 0;
int PotValue = 0;
int cont=0;
int brightness = 0;
void setup(){
Serial.begin(9600);
}
void loop(){
PotValue = analogRead(AI_Pot);
if(PotValue>200)
cont+=1;
else
cont=0;
if(cont>=20){
analogWrite(DO_RedLed, HIGH);
}else analogWrite(DO_RedLed,LOW);
delay(50);
}

Related

why are my first and second LED not lighting up? is it a problem with the for loops?

When I power my Arduino it only lights up the 2-5 and leds and skips the 1st and the 6th led. I tried seeing what's the problem by giving a check on the value of i in the for loops but it is alright.
These are the for loops I am talking about:
for (int i = 0; i < 6; i++)
{
analogWrite(arr[i], ledval);
delay(100);
}
for (int i = 0; i < 6; i++)
{
analogWrite(arr[i], 0);
delay(100);
//digitalWrite(arr[i], LOW);
}
for (int i = 0; i < 6; i++)
{
analogWrite(arr1[i], ledval);
Serial.println(i);
delay(100);
}
for (int i = 0; i < 6; i++)
{
analogWrite(arr1[i], 0);
delay(100);
}
Here is the list:
#include <IRremote.h>
int receiver = 12;
int led1 = 3;
int led2 = 5;
int led3 = 6;
int led4 = 9;
int led5 = 10;
int led6 = 11;
int knob = A0;
int arr[] = {led1, led2, led3, led4, led5, led6};
int arr1[] = {led6, led5, led4, led3, led2, led1};
int worknum1 = 0;
IRrecv irrecv(receiver);
and I have initialized every LED
void setup(){
Serial.begin(9600);
irrecv.enableIRIn();
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(led5, OUTPUT);
pinMode(led6, OUTPUT);
pinMode(knob, INPUT);
}
Do you know what's causing this problem? How can I fix this?
Thanks!
The IR receiving library needs to use a hardware interrupt timer to run code at a certain interval for processing the incoming signal in real time.
It is using timer 2 for this purpose, which is normally responsible for managing the PWM signal on pins 3 and 11 on the Arduino Uno.
See docs:
Incompatibilities to other libraries and Arduino commands like tone() and analogWrite()
If you use a library which requires the same timer as IRremote, you have a problem, since the timer resource cannot be shared simultaneously by both libraries.
[...]
Hardware-PWM signal generation for sending
Board/CPU
Receive & PWM Timers
Hardware-PWM Pin
analogWrite() pins occupied by timer
ATmega328
2
3
3 & 11
Therefore, you cannot use PWM on outputs 3 & 11 together with this library. The docs say you can also manually change which timer is used but that won't help you either because it would then just affect other pins (9 & 10) instead.
If you need more PWM pins, you can instead use an external chip like a TLC5940. See this tutorial for details.

Arduino: for loops in micros()

I have effectively replicated the "no delay blink" example on my Arduino Mega2560 to send pulses to a stepper motor driver. I included a for loop to increment the number of "pulses" given to achieve a single rotation (800 pulses), then delay for a moment and repeat.
I find that the motor is only rotating a fraction of a revolution. It would seem that the micros() running faster than the for loop resulting in missed pulses. I would greatly appreciate if someone could point out why this may be, and how to work around it.
#include <Wire.h>
const int Pul_OUT = 9;
unsigned long previousMicros = 0;
unsigned long Pul_Interval = 100;
int setPosition = 800;
void setup()
{
pinMode(Pul_OUT, OUTPUT);
digitalWrite(Pul_OUT, LOW);
}
void loop()
{
no_delay_Position();
delay(100);
}
int no_delay_Position()
{
for (int i = setPosition; i >= 0 ; i--)
{
unsigned long currentMicros = micros();
if (currentMicros - previousMicros > Pul_Interval)
{
previousMicros = currentMicros;
PulState = !PulState;
digitalWrite(Pul_OUT, PulState);
}
}
}
delay() is measured in milliseconds, microseconds are just a fraction of this.
From the micros() reference:
There are 1,000 microseconds in a millisecond and 1,000,000
microseconds in a second.
Adding the delay(100) in your main loop will also stop the arduino from doing most things. If for some reason you need to use millis() in the outer loop and micros() in the set position loop you could do something like this
#include <Wire.h>
const int Pul_OUT = 9;
unsigned long previousMicros = 0;
unsigned long previousMillis = 0;
int Pul_Interval = 100;
int Main_Interval = 100;
int setPosition = 800;
void setup()
{
pinMode(Pul_OUT, OUTPUT);
digitalWrite(Pul_OUT, LOW);
}
void loop()
{
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > Main_Interval)
{
previousMillis = currentMillis;
no_delay_Position();
}
}
void no_delay_Position()
{
for(int i = setPosition; i >= 0 ; i--)
{
unsigned long currentMicros = micros();
if (currentMicros - previousMicros > Pul_Interval)
{
previousMicros = currentMicros;
PulState = !PulState;
digitalWrite(Pul_OUT, PulState);
}
}
}
The call to no_delay_Position() looks to be set to return an int did you mean to be able to pass in an integer to set the position?
void loop()
{
no_delay_Position(500);
}
void no_delay_Position(int setP)
{
setPosition = setP;
for(int i = setPosition; i >= 0 ; i--)
{
//rest of your code
}
}
Your for loop in no_delay_Position() will decrement i whether a pulse is sent or not (because that is determined by Pul_interval), so i will reach 0 before i pulses are sent.
Also, no_delay_Position() will not return until its for loop is done, and during that time, loop() is blocked.
Also, your Pul_Interval is only 100µs which is 0.1ms. You may want to replace micros() with millis() and see what happens.
BTW 100ms is still fairly quick for pulsing a stepper motor, you could try a larger Pul_Interval if the above is still too fast. There's nothing wrong with testing with a step every second or so, just to see if the algorithm works as expected.

Code for reading input from multiple analog pins on Arduino will not show values

This code that I tried to build myself does not give the output I want.
I'm hoping for an output lik "125, 567, 654, 332, 222, 123".
(6 values, separated by ", ")
If I run another program, I get the values, so there is someting wrong or missing in my code for sure.
#define cellPin A0
#define cellPin A1
#define cellPin A2
#define cellPin A3
#define cellPin A4
#define cellPin A5
float counts = 0;
float const pins = 6; // No of pins from 0 to 5
int timer = 1000;
int stored_pin_values[5];
int average_reads = 20;
void setup() {
Serial.begin(9600); // setup serial
}
void loop() {
for (int x = 0; x < pins; x++) { // counter for each pin, from 0 to 5
for (int i = 0; i < average_reads; i++) { // counter for each reading of the selected pin
if (i == 0) { analogRead("cellPin A"[i]); } // Read pin but do not use first reading
if (i != 0) { counts = analogRead("cellPin A"[i]) + counts; } // read the input pin and add to sum of counts
}
stored_pin_values[x] = counts / (average_reads - 1); // Calc. average of pin. -1 cus we did not use the first reading
counts = 0;
}
for (int y = 0; y < pins; y++) { // Counter for printing average value of each pin
if (y == pins - 1) { Serial.println(stored_pin_values[y]); } //on last pos. print "ln"
else {
Serial.print(stored_pin_values[y]); // print "average pinvalue" separated by ", "
Serial.print(", ");
}
}
delay(timer);
}
you have defined multiple values for cellPin.
#define cellPin A0
#define cellPin A1
#define cellPin A2
#define cellPin A3
#define cellPin A4
#define cellPin A5
I suggest to use a various name like #define cellPin0 A0 #define cellPin1 A1 ...
For second you call analogRead("cellPin A"[i]), passing string with illegal operator for argument: the right method is analogRead(int) -> int.
I write a little sketch for inspiring you:
int analogPins[6]={A0,A1,A2,A3,A4,A5}, //pins
analogValues[6]={0,0,0,0,0,0}; //stores the value of analog read
void setup(){
Serial.begin(9600); //serial communication with baud rate of 9600b/s
}
void loop(){
for(int i=0;i<6;i++){
analogValues[i]=analogRead(analogPins[i]);
}
}
I hope that can help you. Good luck!
Working code after change (note: changed to 5 pin reading instead of 6):
int analogPins[5]={A0,A1,A2,A3,A4}, //pins
analogValues[5]={0,0,0,0,0}; //stores the value of analog read
float counts = 0;
float const pins = 5; // No of pins from 0 to 4
int timer = 1000;
int stored_pin_values[5];
int average_reads = 100;
void setup() {
Serial.begin(9600); // setup serial
}
void loop() {
for (int x = 0; x < pins; x++) { // counter for each pin, from 0 to 4
for (int i = 0; i < average_reads; i++) { // counter for each reading of the selected pin
if (i == 0) { analogRead(analogPins[i]); } // Read pin but do not use first reading
if (i != 0) { counts = analogRead(analogPins[i]) + counts; } // read the input pin and add to sum of counts
}
stored_pin_values[x] = counts / (average_reads - 1); // Calc. average of pin. -1 cus we did not use the first reading
counts = 0;
}
for (int y = 0; y < pins; y++) { // Counter for printing average value of each pin
if (y == pins - 1) { Serial.println(stored_pin_values[y]); } //on last pos. print "ln"
else {
Serial.print(stored_pin_values[y]); // print "average pinvalue" separated by ", "
Serial.print(", ");
}
}
delay(timer);
}

Does arduino count++ has a limit and how to fix it?

I needed to make a meters counter for a work thing, so I decided to just Arduino for it. I found an old encoder, found/wrote a simple code and hacked it all together and encountered a unexpected problem.
For some reason my counter won't count past around 8 meters or 31991 encoder pulses. Once it reaches this 8m limit, the number turns negative and starts counting backwards like -7.9 > -7.8 (i.e. continues counting upward towards 0).
Then it reaches zero and again counts to 8...
This is very strange to me and my limited coding knowledge can't fix it.
Does anyone know how to fix this or what I could do to make it work?
#include <LiquidCrystal.h>
#define inputA_in 6
#define inputB_in 7
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int inputA_V = 0;
int inputB_V = 0;
int inputA = 0;
int inputB = 0;
int counter = 0;
// smeni vrednost tuka pred run
int console_frequency_milliseconds = 200; /// edna sekunda
int aLastState = 0;
int bLastState = 0;
float meters = 0.0;
unsigned long lasttime = 0;
int move_positive = 0;
int move_negative = 0;
int maximum_input_digital_v = 300; //treba da citash od konzola i da gi setirash max i min
int minimum_input_digital_v = 0;
int logical_threshold_v = 150; //brojkive se random staveni
void setup() {
pinMode (inputA_in, INPUT);
pinMode (inputB_in, INPUT);
Serial.begin (9600);
lcd.begin(16, 2);
// Print a message to the LCD
lcd.print("Metraza [m]");
aLastState = inputA;
bLastState = inputB;
lasttime = 0;
}
void loop () {
inputA = digitalRead(inputA_in);
if (inputA != aLastState) {
if (digitalRead(inputB_in) != inputA) {
counter ++;
aLastState = inputA;
} else {
counter --;
aLastState = inputA;
}
}
if (millis() - console_frequency_milliseconds > lasttime)//Detect once every 150ms
{
meters = 0.50014 * counter / 2000;
Serial.print("Position: ");
Serial.println(meters);
lasttime = millis();
lcd.setCursor(0, 1);
//Print a message to second line of LCD
lcd.print(meters);
}
}
Your counter is a simple int,
int counter = 0;
It seems that on your system they are only 16bit wide (with a maximum value of 32767), not surprising.
Use
long int counter = 0;
to get wider variables.
You might also want to change the calculation from
meters = 0.50014 * counter / 2000;
to
meters = 0.50014 * counter / 2000.0;
to avoid losing precision and range. Even with an int that would extend your range from 31991 encoder pulses to 32757 encoder pulses; and analog for the wider range.
You might also like to try changing the counter to an unsigned int or unsigned long int. I did not analyse your whole code, but I think you do not have anything which relies on representation of negative numbers. So you probably could double the range again. But no guarantees, subject to testing.

How can I stop music with a push button?

I would like to know how to stop music with a push button (to stop it exactly at the moment you press the button). Because at the moment my code does what I want(stop the music and turn on a light when I press the press button, but it waits untill the end of the song to stop.
There is my code:
int buttonState = 0;
int speakerOut = 10;
int buttonPin= 7;
int frequency = 500;
int ledPin = 13;
int length = 17; // the number of notes
char notes[] = "gcefgcefgcefgcefga "; // a space represents a rest
//int beats[] = {2,2,1,1,2,2,1,1,2,2,1,1,2,2,1,1};
//int tempo = 250;
int DEBUG = 1;
#define c 3830
#define d 3400
#define e 3038
#define f 2864
#define g 2550
#define a 2272
#define b 2028
#define C 1912
#define R 0
void setup() {
// put your setup code here, to run once:
pinMode(ledPin, OUTPUT);
pinMode(buttonPin,INPUT);
pinMode(speakerOut, OUTPUT);
if (DEBUG) {
Serial.begin(9600); // Set serial out if we want debugging
}
}
// MELODY and TIMING =======================================
// melody[] is an array of notes, accompanied by beats[],
// which sets each note's relative length (higher #, longer note)
int melody[] = { C, b, g, C, b, e, R, C, c, g, a, C };
int beats[] = { 16, 16, 16, 8, 8, 16, 32, 16, 16, 16, 8, 8 };
int MAX_COUNT = sizeof(melody) / 2; // Melody length, for looping.
// Set overall tempo
long tempo = 10000;
// Set length of pause between notes
int pause = 1000;
// Loop variable to increase Rest length
int rest_count = 100; //<-BLETCHEROUS HACK; See NOTES
// Initialize core variables
int tone_ = 0;
int beat = 0;
long duration = 0;
// PLAY TONE ==============================================
// Pulse the speaker to play a tone for a particular duration
void playTone() {
long elapsed_time = 0;
if (tone_ > 0) { // if this isn't a Rest beat, while the tone has
// played less long than 'duration', pulse speaker HIGH and LOW
while (elapsed_time < duration) {
digitalWrite(speakerOut,HIGH);
delayMicroseconds(tone_ / 2);
// DOWN
digitalWrite(speakerOut, LOW);
delayMicroseconds(tone_ / 2);
// Keep track of how long we pulsed
elapsed_time += (tone_);
}
}
else { // Rest beat; loop times delay
for (int j = 0; j < rest_count; j++) { // See NOTE on rest_count
delayMicroseconds(duration);
}
}
}
void loop() {
// put your main code here, to run repeatedly:
buttonState = digitalRead(buttonPin);
if (buttonState==HIGH){
digitalWrite(ledPin, HIGH);
noTone(speakerOut);
}else {
digitalWrite(ledPin, LOW);
digitalWrite(speakerOut,HIGH);
for (int i=0; i<MAX_COUNT; i++) {
tone_ = melody[i];
beat = beats[i];
duration = beat * tempo; // Set up timing
playTone();
// A pause between notes...
delayMicroseconds(pause);
}
}
}
You have 2 options, before playTone() check button and, if pressed, end the for loop.
for (int i=0; i<MAX_COUNT; i++) {
tone_ = melody[i];
beat = beats[i];
duration = beat * tempo; // Set up timing
if (digitalRead(buttonPin)==LOW){
playTone();
} else {
break; //End for loop
}
// A pause between notes...
delayMicroseconds(pause);
}
Or the same but using void loop() as a for loop. A global variable, count between 0 and MAX_COUNT and do the same check. If pressed, count=0; and if not, continue playing the next note. Now, I can't code write this but has no difficult.