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.
Related
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.
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);
}
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);
}
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.
I am trying to implement my own SPI communication from FPGA to Arduino, in which my FPGA serve as MASTER and generate Chip enable and clock for communication. FPGA transmit data at its rising edge and receive data at its falling edge my FPGA code works properly.
In Arduino side I capture this master clock on interrupts and receive data at its rising edge and transmit at its falling edge but communication does not work properly if I increase clock speed from 10 KHz.
According to my understanding, Arduino Due works at 84 MHz and handling 1 MHz interrupts is not a big problem. Can you tell me how I can handle this high-speed clock with an Arduino Due?
Arduino code below:
void ISR1();
// this constant won't change
const int S_CLK = 19; // slow clock in this case FPGA is master
const int MOSI_C = 51; // Master out slave in in this case arduino
//receive data from FPGA
const int MISO_C = 50; // Master in slave out in this case arduino
//transmit data from FPGA
const int SS_C = 53; // the pin that the pushbutton is attached to
const int TRANS_INDEX = 32; //index that is used to transmit data in this
cas 32 bits are transmitted
const int REC_INDEX = 48;
#define CLK_MAIN 84000000UL
//Variables will change
int ss_check = 0; //used for reading of slave select
int mosi_data[REC_INDEX + 2]; //delcare receiving data array length
int count = 0; //used for convertion of bits to bytes
int index_r_stat = 0; //give us a value of status that
how much bits are received
int flag = 0; //used for stop reading s
int miso_out[TRANS_INDEX] = {
1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0
};
int miso_index = 0; //used for above array
int last_clk_state = 1; //used for the detection of rising and
falling edge
int check_clk;
void setup() {
// initialize the button pin as a input
pinMode(S_CLK , INPUT);
pinMode(MOSI_C , INPUT);
pinMode(MISO_C , OUTPUT);
pinMode(SS_C , INPUT);
// initialize serial communication
Serial.begin(9600);
}
void loop() {
// read the pushbutton input pin
ss_check = digitalRead(SS_C);
//Serial.println(ss_check);
//WAIT until slave select is not read
if (ss_check == 0) {
//attach interrupt so that data is
attachInterrupt(digitalPinToInterrupt(S_CLK), ISR1, CHANGE);
}
if ((index_r_stat == (REC_INDEX + 1)) && (flag == 0)) {
for (int i = 1; i < (REC_INDEX + 1); i = i + 1) {
Serial.print(mosi_data[i]);
flag = 1;
if (count < 7) {
count = count + 1;
} else {
count = 0;
Serial.println();
}
}
}
}
void ISR1() {
if ((last_clk_state == 1) && (digitalRead(S_CLK) == 0)) {
check_clk = 0;
//this code is used to transmit data to FPGA
if (miso_index < TRANS_INDEX - 1) {
digitalWrite(MISO_C, miso_out[miso_index]);
miso_index = miso_index + 1;
} else {
miso_index = miso_index;
}
} else {
check_clk = 1;
//this code is used for reading data from FPGA
if (index_r_stat < (REC_INDEX + 1)) {
mosi_data[index_r_stat] = digitalRead( MOSI_C);
index_r_stat = index_r_stat + 1;
} else {
detachInterrupt(S_CLK);
index_r_stat = index_r_stat;
}
}
last_clk_state = digitalRead(S_CLK);
}