processing + bitWrite + arduino - arduino

I am working with an Arduino and Processing with the Arduino library.
I get the error "The function bitWrite(byte, int, int) does not exist.";
it seams that processing + Arduino bitWrite function are not working together.
its raised due to this line:
arduino.bitWrite(data,desiredPin,desiredState);
my goal in this project is modifying a music reactive sketch to work with shift registers.
Here is my full code:
Arduino_Shift_display
import ddf.minim.*;
import ddf.minim.analysis.*;
import processing.serial.*;
import cc.arduino.*;
int displayNum = 8;
Arduino arduino;
//Set these in the order of frequency - 0th pin is the lowest frequency,
//while the final pin is the highest frequency
int[] lastFired = new int[displayNum];
int datapin = 2;
int clockpin = 3;
int latchpin = 4;
int switchpin = 7;
byte data = 0;
//Change these to mess with the flashing rates
//Sensitivity is the shortest possible interval between beats
//minTimeOn is the minimum time an LED can be on
int sensitivity = 75;
int minTimeOn = 50;
String mode;
String source;
Minim minim;
AudioInput in;
AudioPlayer song;
BeatDetect beat;
//Used to stop flashing if the only signal on the line is random noise
boolean hasInput = false;
float tol = 0.005;
void setup(){
// shift register setup
arduino.pinMode(datapin, arduino.OUTPUT);
arduino.pinMode(clockpin, arduino.OUTPUT);
arduino.pinMode(latchpin, arduino.OUTPUT);
arduino.digitalWrite(switchpin, arduino.HIGH);
//Uncomment the mode/source pair for the desired input
//Shoutcast radio stream
//mode = "radio";
//source = "http://scfire-ntc-aa05.stream.aol.com:80/stream/1018";
//mode = "file";
//source = "/path/to/mp3";
mode = "mic";
source = "";
size(512, 200, P2D);
minim = new Minim(this);
arduino = new Arduino(this, Arduino.list()[1]);
minim = new Minim(this);
if (mode == "file" || mode == "radio"){
song = minim.loadFile(source, 2048);
song.play();
beat = new BeatDetect(song.bufferSize(), song.sampleRate());
beat.setSensitivity(sensitivity);
} else if (mode == "mic"){
in = minim.getLineIn(Minim.STEREO, 2048);
beat = new BeatDetect(in.bufferSize(), in.sampleRate());
beat.setSensitivity(sensitivity);
}
}
void shiftWrite(int desiredPin, int desiredState)
// This function lets you make the shift register outputs
// HIGH or LOW in exactly the same way that you use digitalWrite().
// Like digitalWrite(), this function takes two parameters:
// "desiredPin" is the shift register output pin
// you want to affect (0-7)
// "desiredState" is whether you want that output
// to be HIGH or LOW
// Inside the Arduino, numbers are stored as arrays of "bits",
// each of which is a single 1 or 0 value. Because a "byte" type
// is also eight bits, we'll use a byte (which we named "data"
// at the top of this sketch) to send data to the shift register.
// If a bit in the byte is "1", the output will be HIGH. If the bit
// is "0", the output will be LOW.
// To turn the individual bits in "data" on and off, we'll use
// a new Arduino commands called bitWrite(), which can make
// individual bits in a number 1 or 0.
{
// First we'll alter the global variable "data", changing the
// desired bit to 1 or 0:
arduino.bitWrite(data,desiredPin,desiredState);
// Now we'll actually send that data to the shift register.
// The shiftOut() function does all the hard work of
// manipulating the data and clock pins to move the data
// into the shift register:
arduino.shiftOut(datapin, clockpin, MSBFIRST, data);
// Once the data is in the shift register, we still need to
// make it appear at the outputs. We'll toggle the state of
// the latchPin, which will signal the shift register to "latch"
// the data to the outputs. (Latch activates on the high-to
// -low transition).
arduino.digitalWrite(latchpin, arduino.HIGH);
arduino.digitalWrite(latchpin, arduino.LOW);
}
void draw(){
if (mode == "file" || mode == "radio"){
beat.detect(song.mix);
drawWaveForm((AudioSource)song);
} else if (mode == "mic"){
beat.detect(in.mix);
drawWaveForm((AudioSource)in);
}
if (hasInput){ //hasInput is set within drawWaveForm
for (int i=0; i<displayNum-1; i++){
if ( beat.isRange( i+1, i+1, 1) ){
shiftWrite(i, 1);
lastFired[i] = millis();
} else {
if ((millis() - lastFired[i]) > minTimeOn){
shiftWrite(i, 0);
}
}
}
}
} //End draw method
//Display the input waveform
//This method sets 'hasInput' - if any sample in the signal has a value
//larger than 'tol,' there is a signal and the lights should flash.
//Otherwise, only noise is present and the lights should stay off.
void drawWaveForm(AudioSource src){
background(0);
stroke(255);
hasInput = false;
for(int i = 0; i < src.bufferSize() - 1; i++)
{
line(i, 50 + src.left.get(i)*50, i+1, 50 + src.left.get(i+1)*50);
line(i, 150 + src.right.get(i)*50, i+1, 150 + src.right.get(i+1)*50);
if (!hasInput && (abs(src.left.get(i)) > tol || abs(src.right.get(i)) > tol)){
hasInput = true;
}
}
}
void resetPins(){
for (int i=0; i<ledPins.length; i++){
arduino.digitalWrite(ledPins[i], Arduino.LOW);
}
}
void stop(){
resetPins();
if (mode == "mic"){
in.close();
}
minim.stop();
super.stop();
}
BeatListener
class BeatListener implements AudioListener
{
private BeatDetect beat;
private AudioPlayer source;
BeatListener(BeatDetect beat, AudioPlayer source)
{
this.source = source;
this.source.addListener(this);
this.beat = beat;
}
void samples(float[] samps)
{
beat.detect(source.mix);
}
void samples(float[] sampsL, float[] sampsR)
{
beat.detect(source.mix);
}
}

You can achieve the same thing using standard bitwise operators. To turn a bit on:
data |= 1 << bitNumber;
The right-hand side (1 << bitNumber) is a bit-shift operation to create a suitable bit-mask. It takes the single '1' bit and moves it left until it reaches the desired position. The bitwise-or assignment (|=) combines that new bit-mask with the existing bits in data. This turns the desired bit on, but leaves the rest untouched.
The code to turn a bit off is slightly different:
data &= ~(1 << bitNumber);
You can see the same bit-shift operation here. However, it's preceded by the unary negation operator (~). This swaps all the 1's for 0's, and all the 0's for 1's. The result is the exact opposite of the bit-mask we used before. You can't do a bitwise-or operation this time though, or else you'll turn all the other bits on. The bitwise-and assignment (&=) is used instead to combine this mask with the data variable. This ensures the desired bit is turned off, and the rest are untouched.
In your code, desiredPin is the equivalent of bitNumber.
A full explanation of how bitwise operations work can be quite lengthy. I'd recommend looking for a good tutorial online if you need more help with that.

There are also the bitSet and bitClear Arduino macros that make the code a little more readable than bit shifting and using AND and OR. The format is either bitSet(what_to_modify,bit_number) and bitClear(what_to_modify,bit_number). These translate into very efficient code and can be used to manipulate both, variables and hardware registers. So for example, if you wanted to turn on pin 13 on the Arduino UNO, you would first need to look up that Arduino pin 13 is actually pin 5 on PORTB of the Atmel atmega328 chip. So the command would be:
bitSet(PORTB,5);

Related

Receiving a string through UART in STM32F4

I've written this code to receive a series of char variable through USART6 and have them stored in a string. But the problem is first received value is just a junk! Any help would be appreciated in advance.
while(1)
{
//memset(RxBuffer, 0, sizeof(RxBuffer));
i = 0;
requestRead(&dt, 1);
RxBuffer[i++] = dt;
while (i < 11)
{
requestRead(&dt, 1);
RxBuffer[i++] = dt;
HAL_Delay(5);
}
function prototype
static void requestRead(char *buffer, uint16_t length)
{
while (HAL_UART_Receive_IT(&huart6, buffer, length) != HAL_OK)
HAL_Delay(10);
}
First of all, the HAL_Delay seems to be redundant. Is there any particular reason for it?
The HAL_UART_Receive_IT function is used for non-blocking mode. What you have written seems to be more like blocking mode, which uses the HAL_UART_Receive function.
Also, I belive you need something like this:
Somewhere in the main:
// global variables
volatile uint8_t Rx_byte;
volatile uint8_t Rx_data[10];
volatile uint8_t Rx_indx = 0;
HAL_UART_Receive_IT(&huart1, &Rx_byte, 1);
And then the callback function:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == UART1) { // Current UART
Rx_data[Rx_indx++] = Rx_byte; // Add data to Rx_Buffer
}
HAL_UART_Receive_IT(&huart1, &Rx_byte, 1);
}
The idea is to receive always only one byte and save it into an array. Then somewhere check the number of received bytes or some pattern check, etc and then process the received frame.
On the other side, if the number of bytes is always same, you can change the "HAL_UART_Receive_IT" function and set the correct bytes count.

Trying to extract longitude and latitude from gps using arduino and neo 6m module but the loop goes up to infinity

I'm new to arduino and trying to extract gps coordinate using neo 6m module using arduino but the loop is running till infinity. Can you please help me why it is not breaking.
void gpsEvent()
{
gpsString = "";
while (1)
{
while (gps.available() > 0) //Serial incoming data from GPS
{
char inChar = (char)gps.read();
gpsString += inChar;//store incoming data from GPS to temparary string str[]
i++;
// Serial.print(inChar);
if (i < 7)
{
if (gpsString[i-1] != test[i-1]) //check for right string
{
i = 0;
gpsString = "";
}
}
if (inChar == '\r')
{
if (i > 60)
{
gps_status = 1;
break;
}
else
{
i = 0;
}
}
}
if (gps_status)
break;
}
}
void get_gps()
{
gps_status = 0;
int x = 0;
while (gps_status == 0)
{
gpsEvent();
int str_lenth = i;
coordinate2dec();
i = 0;
x = 0;
str_lenth = 0;
}
}
I have called get_gps(); in the void setup() loop to initialize the system but the gpsEvent function which is used to extract the correct string from data is running till infinite can you pls help. The reference of the code is from https://circuitdigest.com/microcontroller-projects/arduino-based-accident-alert-system-using-gps-gsm-accelerometer
but have made few changes of my own but not in the programming for the gps module.
I think one of the errors is gpsString += inChar;.
This is not Python. You are adding the value of a character to a string pointer.
You should create a buffer with a maximum length, insert a char and check buffer overflow.
Also i seems not be defined. And in C is very bad practice to use global variables as you are doing. Keep one i in the function. Check again the string length.
In general, it seems you are using a language you do not know enough to write simple programs (string manipulation is basic on C). Either learn better C or look for a python implementation (or just link) of the gps library.

Run two functions at once

This program is a simple program designed to plot at the same time both your & Uc on the serial monitor. Arduino runs through the first for loop & plot the F1 function and after that does the same with F2. My objective is to plot them both at the same time.
My idea is to actually take a small fraction of time, let's say 10 ms, to plot F1 & the next 10 ms to plot F2, but I don't know how to write this down. I think the millis function is the solution, but I'm not quite sure how to implement it.
const short int R = 5000;
const float C = 0.0005;
const float TE = 0.1;
const float Tau = R*C;
const short int E = 5;
float t, Tinit,Tfin;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
//F1
for ( t = 0; t <= 20; t = t+TE)
{
float Ur = E*exp(-t/Tau);
Serial.println (Ur);
}
//F2
for ( t = 0; t <= 20; t = t+TE)
{
float Uc = E*(1-exp(-t/Tau));
Serial.println (Uc);
}
}
Thread can be used to solve your problem . It has a huge documentation , it is widely used library for Arduino(unofficial).
Give it a try.
It will be easy for you, if you see these :
Example - 1 (thread instance example)
Example - 2 (callback example)
Example - 3 (It is still buggy , but I think it will help)
If you want to do it without libraries , then you need to create two functions , without those loops . Like
void f1()
{
float Ur = E*exp(-t/Tau);
Serial.println (Ur);
}
void f2()
{
float Uc = E*(1-exp(-t/Tau));
Serial.println (Uc);
}
Now inside "void loop()" you can implement the basic logic of threading , which will be pretty rough , but fulfill your requirements. Like :
void loop() {
unsigned long now = millis();
static unsigned long last_finger_update;
if (now - last_finger_update >= FINGER_UPDATE_PERIOD) {
last_finger_update = now;
f1();
}
static unsigned long last_wrist_update;
if (now - last_wrist_update >= WRIST_UPDATE_PERIOD) {
last_wrist_update = now;
f2();
}
}
You have to declare two variables
const unsigned long FINGER_UPDATE_PERIOD = 1000;
const unsigned long WRIST_UPDATE_PERIOD = 1000;
All time units are in milliseconds. This strategy is collected from internet.
The most deterministic way of handling this is simply:
for (t = 0; t <= 20; t = t + TE) {
float Ur = E*exp(-t/Tau);
float Uc = E*(1-exp(-t/Tau));
Serial.println (Ur);
Serial.println (Uc);
}
More generally, you can implement a primitive resource scheduler:
while (true) {
task_one();
task_two();
}
You can do that Easily if you run RTOS in MCU as you know other solutions will also be sequential...
I've been using TridentTD_EasyFreeRTOS library it has easy way of having multiple tasks and controlling them in different sketch files..

QAudioOutput underrun issue on Realtime Play from Microphone with QAudioInput

Sometimes I am getting "underrun occured" from ALSA lib and that means the audioouput is not getting the values on time to play. Alsa then repeats the old buffer values on the speaker.
How can I avoid underruns on QAudioOuput?
I am using Qt5.9.1 and ARM Based CPU running on Debian 8.
I tried to change the buffersize:
audioOutput->setBufferSize(144000);
qDebug()<<"buffersize "<<audioOutput->bufferSize()<<" period size" .
<<audioOutput->periodSize();
I get: buffersize 144000 period size 0
and after audiOutput->start() I get: buffersize 19200 period size 3840
Here is what I am doing:
audioOutput->setBufferSize(144000);
qDebug()<<"buffersize "<<audioOutput->bufferSize()<<" period size" .
<<audioOutput->periodSize();
m_audioInput = audioInput->start();
m_audioOutput = audioOutput->start();
qDebug()<<"buffersize "<<audioOutput->bufferSize()<<" period size"<
<<audioOutput->periodSize();
connect(m_audioInput, SIGNAL(readyRead()), SLOT(readBufferSlot()));
Once audio data gets recorded I write to the QIODevice m_audioOutput the values from QIODevice m_audioInput.
So I think I have a timing issue sometimes and the audio interval for both is 1000ms before and after start().
Why cant I increase the buffer size? And how can I avoid underrun?
Based on my experience with QAudioOutput, it's buffer is intended just to keep real-time playing, you can't for example drop 1 minute of sound directly to the QIODevice expecting it gets buffered and played sequentially, but it do not means that you can't buffer sound, just means that you need to do it by yourself.
I made the following example in "C-Style" to make an all-in-one solution, it buffers 1000 milliseconds (1 second) of the input before play it.
The event loop needs to be available to process the Qt SIGNALs.
In my tests, 1 second buffering is fairly enough to avoid under runs.
#include <QtCore>
#include <QtMultimedia>
#define MAX_BUFFERED_TIME 1000
static inline int timeToSize(int ms, const QAudioFormat &format)
{
return ((format.channelCount() * (format.sampleSize() / 8) * format.sampleRate()) * ms / 1000);
}
struct AudioContext
{
QAudioInput *m_audio_input;
QIODevice *m_input_device;
QAudioOutput *m_audio_output;
QIODevice *m_output_device;
QByteArray m_buffer;
QAudioDeviceInfo m_input_device_info;
QAudioDeviceInfo m_output_device_info;
QAudioFormat m_format;
int m_time_to_buffer;
int m_max_size_to_buffer;
int m_size_to_buffer;
bool m_buffer_requested = true; //Needed
bool m_play_called = false;
};
void play(AudioContext *ctx)
{
//Set that last async call was triggered
ctx->m_play_called = false;
if (ctx->m_buffer.isEmpty())
{
//If data is empty set that nothing should be played
//until the buffer has at least the minimum buffered size already set
ctx->m_buffer_requested = true;
return;
}
else if (ctx->m_buffer.size() < ctx->m_size_to_buffer)
{
//If buffer doesn't contains enough data,
//check if exists a already flag telling that the buffer comes
//from a empty state and should not play anything until have the minimum data size
if (ctx->m_buffer_requested)
return;
}
else
{
//Buffer is ready and data can be played
ctx->m_buffer_requested = false;
}
int readlen = ctx->m_audio_output->periodSize();
int chunks = ctx->m_audio_output->bytesFree() / readlen;
//Play data while it's available in the output device
while (chunks)
{
//Get chunk from the buffer
QByteArray samples = ctx->m_buffer.mid(0, readlen);
int len = samples.size();
ctx->m_buffer.remove(0, len);
//Write data to the output device after the volume was applied
if (len)
{
ctx->m_output_device->write(samples);
}
//If chunk is smaller than the output chunk size, exit loop
if (len != readlen)
break;
//Decrease the available number of chunks
chunks--;
}
}
void preplay(AudioContext *ctx)
{
//Verify if exists a pending call to play function
//If not, call the play function async
if (!ctx->m_play_called)
{
ctx->m_play_called = true;
QTimer::singleShot(0, [=]{play(ctx);});
}
}
void init(AudioContext *ctx)
{
/***** INITIALIZE INPUT *****/
//Check if format is supported by the choosen input device
if (!ctx->m_input_device_info.isFormatSupported(ctx->m_format))
{
qDebug() << "Format not supported by the input device";
return;
}
//Initialize the audio input device
ctx->m_audio_input = new QAudioInput(ctx->m_input_device_info, ctx->m_format, qApp);
ctx->m_input_device = ctx->m_audio_input->start();
if (!ctx->m_input_device)
{
qDebug() << "Failed to open input audio device";
return;
}
//Call the readyReadPrivate function when data are available in the input device
QObject::connect(ctx->m_input_device, &QIODevice::readyRead, [=]{
//Read sound samples from input device to buffer
ctx->m_buffer.append(ctx->m_input_device->readAll());
preplay(ctx);
});
/***** INITIALIZE INPUT *****/
/***** INITIALIZE OUTPUT *****/
//Check if format is supported by the choosen output device
if (!ctx->m_output_device_info.isFormatSupported(ctx->m_format))
{
qDebug() << "Format not supported by the output device";
return;
}
int internal_buffer_size;
//Adjust internal buffer size
if (ctx->m_format.sampleRate() >= 44100)
internal_buffer_size = (1024 * 10) * ctx->m_format.channelCount();
else if (ctx->m_format.sampleRate() >= 24000)
internal_buffer_size = (1024 * 6) * ctx->m_format.channelCount();
else
internal_buffer_size = (1024 * 4) * ctx->m_format.channelCount();
//Initialize the audio output device
ctx->m_audio_output = new QAudioOutput(ctx->m_output_device_info, ctx->m_format, qApp);
//Increase the buffer size to enable higher sample rates
ctx->m_audio_output->setBufferSize(internal_buffer_size);
//Compute the size in bytes to be buffered based on the current format
ctx->m_size_to_buffer = int(timeToSize(ctx->m_time_to_buffer, ctx->m_format));
//Define a highest size that the buffer are allowed to have in the given time
//This value is used to discard too old buffered data
ctx->m_max_size_to_buffer = ctx->m_size_to_buffer + int(timeToSize(MAX_BUFFERED_TIME, ctx->m_format));
ctx->m_output_device = ctx->m_audio_output->start();
if (!ctx->m_output_device)
{
qDebug() << "Failed to open output audio device";
return;
}
//Timer that helps to keep playing data while it's available on the internal buffer
QTimer *timer_play = new QTimer(qApp);
timer_play->setTimerType(Qt::PreciseTimer);
QObject::connect(timer_play, &QTimer::timeout, [=]{
preplay(ctx);
});
timer_play->start(10);
//Timer that checks for too old data in the buffer
QTimer *timer_verifier = new QTimer(qApp);
QObject::connect(timer_verifier, &QTimer::timeout, [=]{
if (ctx->m_buffer.size() >= ctx->m_max_size_to_buffer)
ctx->m_buffer.clear();
});
timer_verifier->start(qMax(ctx->m_time_to_buffer, 10));
/***** INITIALIZE OUTPUT *****/
qDebug() << "Playing...";
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
AudioContext ctx;
QAudioFormat format;
format.setCodec("audio/pcm");
format.setSampleRate(44100);
format.setChannelCount(1);
format.setSampleSize(16);
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
ctx.m_format = format;
ctx.m_input_device_info = QAudioDeviceInfo::defaultInputDevice();
ctx.m_output_device_info = QAudioDeviceInfo::defaultOutputDevice();
ctx.m_time_to_buffer = 1000;
init(&ctx);
return a.exec();
}

Arduino - How to control piezo with button?

What I am trying to achieve is a button that acts as an on/off switch for playing a tune on a piezo. Initially I want the piezo not to make any sound until the user presses a button, and then they can turn the piezo off by pressing the same button. I'm wondering if anyone can help me figure out what code I need to add to this to get this kind of button functionality.
This is a modified version of the toneMelody sketch that comes with Arduino IDE, I have a button attached to Pin 12, and a Piezo to Pin 8.
#include "pitches.h"
// notes in the melody:
int melody[] ={
NE5,NF5,NG5,ND6,0,NC6,NC6,NB5,NG5,NF5,0,NF5,NF5,NE5,NC5,NF5,NE5,ND5,NC5,NE5,ND5,0,NE5,NF5,NG5,ND6,0,NC6,NC6,NB5,NG5,NF5,0,NF5,NF5,NE5,NC5,NF5,NE5,ND5,NC5,NE5,ND5,0,
0,NC5,NE5,NG5,NG5,NE5,ND5,NE5,ND5,0,NC5,NE5,NG5,NG5,NE5,ND5,0,NE5,0,NC5,NE5,NG5,NG5,NE5,ND5,NE5,ND5,0,NC5,NE5,NG5,NG5,NA5,NE5,0,NE5,
0,NC5,NE5,NG5,NG5,NE5,ND5,NE5,ND5,0,NC5,NE5,NG5,NG5,NE5,ND5,0,NE5,0,NC5,NE5,NG5,NG5,NE5,ND5,NE5,ND5,NF5,0,NE5,0,NC5,NF5,0,NE5,0,NC5,
NE5,NE5,NE5,0,NE5,0,ND5,NE5,NE5,NE5,0,NE5,0,ND5,NE5,NE5,NE5,0,NE5,0,ND5,ND5,NB4,NB4,0,NC5,0,NG5,
NE5,NE5,NE5,0,NE5,0,ND5,NE5,NE5,NE5,0,NE5,0,ND5,NE5,NE5,NE5,0,NE5,0,ND5,ND5,
NE5,NF5,NG5,ND6,0,NC6,NC6,NB5,NG5,NF5,0,NF5,NF5,NE5,NC5,NF5,NE5,ND5,NC5,NE5,ND5,0,NE5,NF5,NG5,ND6,0,NC6,NC6,NB5,NG5,NF5,0,NF5,NF5,NE5,NC5,NF5,NE5,ND5,NC5,NE5,ND5,0,
NE5,NF5,NE5,ND5,ND5,NC5,NC5,NC5,ND5,ND5,NE5,0,NE5,NF5,NE5,ND5,ND5,NC5,NC5,NC5,NG5,ND5,0,
NE5,NF5,NE5,ND5,ND5,NC5
};
// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
8,8,8,4,8,4,8,8,8,4,8,4,8,8,8,4,4,8,8,8,2,8,8,8,8,4,8,4,8,8,8,4,8,4,8,8,8,4,4,8,8,8,2,8,
8,8,8,8,8,16,8,16,8,8,8,8,8,8,16,8,16,8,8,8,8,8,8,16,8,16,8,8,8,8,8,8,16,8,16,8,
8,8,8,8,8,16,8,16,8,8,8,8,8,8,16,8,16,8,8,8,8,8,8,16,8,16,8,8,16,8,16,8,8,16,8,16,8,
4,4,8,16,8,16,8,4,4,8,16,8,16,8,4,4,8,16,8,16,8,4,4,8,16,8,16,8,
4,4,8,16,8,16,8,4,4,8,16,8,16,8,4,4,8,16,8,16,8,2,
8,8,8,4,8,4,8,8,8,4,8,4,8,8,8,4,4,8,8,8,2,8,8,8,8,4,8,4,8,8,8,4,8,4,8,8,8,4,4,8,8,8,2,8,
8,8,8,8,4,4,8,8,8,4,2,8,8,8,8,8,4,4,8,8,8,2,8,
8,8,8,8,4,1
};
void setup() {
// iterate over the notes of the melody:
for (int thisNote = 0; thisNote < 240; thisNote++) {
// to calculate the note duration, take one second
// divided by the note type.
//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
int noteDuration = 1000/noteDurations[thisNote];
tone(8, melody[thisNote],noteDuration);
// to distinguish the notes, set a minimum time between them.
// the note's duration + 30% seems to work well:
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
// stop the tone playing:
noTone(8);
}
}
void loop() {
// no need to repeat the melody.
}
The way I would use a button would be like this. I added comments above and below were I added stuff. The out come of this will be that when you press the button the whole song will play then stop until you press the button again. You can see what kind of button I am taking about here http://arduino.cc/en/Tutorial/Button it also gives you some example code, for you to look at just incase I messed up, if I did mess up
just message me and I will show you how to fix.
#include "pitches.h"
// notes in the melody:
int melody[] ={
NE5,NF5,NG5,ND6,0,NC6,NC6,NB5,NG5,NF5,0,NF5,NF5,NE5,NC5,NF5,NE5,ND5,NC5,NE5,ND5,0,NE5,NF5,
NG5,ND6,0,NC6,NC6,NB5,NG5,NF5,0,NF5,NF5,NE5,NC5,NF5,NE5,ND5,NC5,NE5,ND5,0,
0,NC5,NE5,NG5,NG5,NE5,ND5,NE5,ND5,0,NC5,NE5,NG5,NG5,NE5,ND5,0,NE5,0,NC5,NE5,NG5,NG5,NE5,ND
5,NE5,ND5,0,NC5,NE5,NG5,NG5,NA5,NE5,0,NE5,
0,NC5,NE5,NG5,NG5,NE5,ND5,NE5,ND5,0,NC5,NE5,NG5,NG5,NE5,ND5,0,NE5,0,NC5,NE5,NG5,NG5,NE5,ND
5,NE5,ND5,NF5,0,NE5,0,NC5,NF5,0,NE5,0,NC5,
NE5,NE5,NE5,0,NE5,0,ND5,NE5,NE5,NE5,0,NE5,0,ND5,NE5,NE5,NE5,0,NE5,0,ND5,ND5,NB4,NB4,0,NC5,
0,NG5,
NE5,NE5,NE5,0,NE5,0,ND5,NE5,NE5,NE5,0,NE5,0,ND5,NE5,NE5,NE5,0,NE5,0,ND5,ND5,
NE5,NF5,NG5,ND6,0,NC6,NC6,NB5,NG5,NF5,0,NF5,NF5,NE5,NC5,NF5,NE5,ND5,NC5,NE5,ND5,0,NE5,NF5,
NG5,ND6,0,NC6,NC6,NB5,NG5,NF5,0,NF5,NF5,NE5,NC5,NF5,NE5,ND5,NC5,NE5,ND5,0,
NE5,NF5,NE5,ND5,ND5,NC5,NC5,NC5,ND5,ND5,NE5,0,NE5,NF5,NE5,ND5,ND5,NC5,NC5,NC5,NG5,ND5,0,
NE5,NF5,NE5,ND5,ND5,NC5
};
// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
8,8,8,4,8,4,8,8,8,4,8,4,8,8,8,4,4,8,8,8,2,8,8,8,8,4,8,4,8,8,8,4,8,4,8,8,8,4,4,8,8,8,2,8,
8,8,8,8,8,16,8,16,8,8,8,8,8,8,16,8,16,8,8,8,8,8,8,16,8,16,8,8,8,8,8,8,16,8,16,8,
8,8,8,8,8,16,8,16,8,8,8,8,8,8,16,8,16,8,8,8,8,8,8,16,8,16,8,8,16,8,16,8,8,16,8,16,8,
4,4,8,16,8,16,8,4,4,8,16,8,16,8,4,4,8,16,8,16,8,4,4,8,16,8,16,8,
4,4,8,16,8,16,8,4,4,8,16,8,16,8,4,4,8,16,8,16,8,2,
8,8,8,4,8,4,8,8,8,4,8,4,8,8,8,4,4,8,8,8,2,8,8,8,8,4,8,4,8,8,8,4,8,4,8,8,8,4,4,8,8,8,2,8,
8,8,8,8,4,4,8,8,8,4,2,8,8,8,8,8,4,4,8,8,8,2,8,
8,8,8,8,4,1
};
//int to identify what digital pin the button is hooked up to
// can Chang 2 if put button on a different pin
int buttonPin = 2;
void setup() {
//says button pin is a input
pinMode(buttonPin, INPUT);
// I might say make a int = to the pin you have
// your sound maker on, name it soundMakerPin, and the uncomment the line below
// pinMode(soundMakerPin, OUTPUT);
}
void loop(){
// read the button
buttonState = digitalRead(buttonPin);
// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
if (buttonState == HIGH) {
// play song
song();
}
}
//function named song, call this and your song should play
void song(){
// iterate over the notes of the melody:
for (int thisNote = 0; thisNote < 240; thisNote++) {
// to calculate the note duration, take one second
// divided by the note type.
//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
int noteDuration = 1000/noteDurations[thisNote];
tone(8, melody[thisNote],noteDuration);
// to distinguish the notes, set a minimum time between them.
// the note's duration + 30% seems to work well:
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
// stop the tone playing:
noTone(8);
}
}

Resources