Hmmm.
Un-comment some of the Serial.print statements in check_switches(). Then open up the Serial Monitor so we can see if it is getting called.
Waveshield + Arduino Mega -> Distorted sound
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- adafruit_support_bill
- Posts: 88086
- Joined: Sat Feb 07, 2009 10:11 am
- dy-wen
- Posts: 30
- Joined: Wed Sep 16, 2009 11:31 am
Re: Waveshield + Arduino Mega -> Distorted sound
ooff!
Weird stuff going on -> see the screenshot of the serial monitor output.
When I don't take out the usb cable of the Arduino, my whole computer freezes and the data displayed in the serial monitor first fly by, then they start trickling in until it freezes. I'll check what the other Serial print stuff gives as messages.
I have only uncommented one part of the Serial print output of the check_switches:
I'll check what the other Serial print stuff gives similar messages -> no change in state - if I press a button or not.
For the record, this is the code I use at the moment.
Weird stuff going on -> see the screenshot of the serial monitor output.
When I don't take out the usb cable of the Arduino, my whole computer freezes and the data displayed in the serial monitor first fly by, then they start trickling in until it freezes. I'll check what the other Serial print stuff gives as messages.
I have only uncommented one part of the Serial print output of the check_switches:
Code: Select all
void check_switches()
{
static byte previousstate[NUMBUTTONS];
static byte currentstate[NUMBUTTONS];
byte index;
for (index = 0; index < NUMBUTTONS; index++) {
currentstate[index] = digitalRead(buttons[index]); // read the button
/*
Serial.print(index, DEC);
Serial.print(": cstate=");
Serial.print(currentstate[index], DEC);
Serial.print(", pstate=");*/
Serial.print(previousstate[index], DEC);
Serial.print(", press=");
if (currentstate[index] == previousstate[index]) {
if ((pressed[index] == LOW) && (currentstate[index] == LOW)) {
// just pressed
justpressed[index] = 1;
}
else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) {
// just released
justreleased[index] = 1;
}
pressed[index] = !currentstate[index]; // remember, digital HIGH means NOT pressed
}
//Serial.println(pressed[index], DEC);
previousstate[index] = currentstate[index]; // keep a running tally of the buttons
}
}
For the record, this is the code I use at the moment.
Code: Select all
#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"
SdReader card; // This object holds the information for the card
FatVolume vol; // This holds the information for the partition on the card
FatReader root; // This holds the information for the filesystem on the card
FatReader f; // This holds the information for the file we're play
WaveHC wave; // This is the only wave (audio) object, since we will only play one at a time
#define DEBOUNCE 5 // button debouncer
// here is where we define the buttons that we'll use. button "1" is the first, button "6" is the 6th, etc
byte buttons[] = {22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41};
// This handy macro lets us determine how big the array up above is, by checking the size
#define NUMBUTTONS sizeof(buttons)
// we will track if a button is just pressed, just released, or 'pressed' (the current state
volatile byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];
// this handy function will return the number of bytes currently free in RAM, great for debugging!
int freeRam(void)
{
extern int __bss_end;
extern int *__brkval;
int free_memory;
if((int)__brkval == 0) {
free_memory = ((int)&free_memory) - ((int)&__bss_end);
}
else {
free_memory = ((int)&free_memory) - ((int)__brkval);
}
return free_memory;
}
void sdErrorCheck(void)
{
if (!card.errorCode()) return;
putstring("\n\rSD I/O error: ");
Serial.print(card.errorCode(), HEX);
putstring(", ");
Serial.println(card.errorData(), HEX);
while(1);
}
void setup() {
byte i;
// set up serial port
Serial.begin(9600);
putstring_nl("WaveHC with ");
Serial.print(NUMBUTTONS, DEC);
putstring_nl("buttons");
putstring("Free RAM: "); // This can help with debugging, running out of RAM is bad
Serial.println(freeRam()); // if this is under 150 bytes it may spell trouble!
// Set the output pins for the DAC control. This pins are defined in the library
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
// pin13 LED
pinMode(13, OUTPUT);
// Make input & enable pull-up resistors on switch pins
for (i=0; i< NUMBUTTONS; i++) {
pinMode(buttons[i], INPUT);
digitalWrite(buttons[i], HIGH);
}
// if (!card.init(true)) { //play with 4 MHz spi if 8MHz isn't working for you
if (!card.init()) { //play with 8 MHz spi (default faster!)
putstring_nl("Card init. failed!"); // Something went wrong, lets print out why
sdErrorCheck();
while(1); // then 'halt' - do nothing!
}
// enable optimize read - some cards may timeout. Disable if you're having problems
card.partialBlockRead(true);
// Now we will look for a FAT partition!
uint8_t part;
for (part = 0; part < 5; part++) { // we have up to 5 slots to look in
if (vol.init(card, part))
break; // we found one, lets bail
}
if (part == 5) { // if we ended up not finding one :(
putstring_nl("No valid FAT partition!");
sdErrorCheck(); // Something went wrong, lets print out why
while(1); // then 'halt' - do nothing!
}
// Lets tell the user about what we found
putstring("Using partition ");
Serial.print(part, DEC);
putstring(", type is FAT");
Serial.println(vol.fatType(),DEC); // FAT16 or FAT32?
// Try to open the root directory
if (!root.openRoot(vol)) {
putstring_nl("Can't open root dir!"); // Something went wrong,
while(1); // then 'halt' - do nothing!
}
// Whew! We got past the tough parts.
putstring_nl("Ready!");
TCCR2A = 0;
TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;
//Timer2 Overflow Interrupt Enable
TIMSK2 |= 1<<TOIE2;
}
SIGNAL(TIMER2_OVF_vect) {
check_switches();
}
void check_switches()
{
static byte previousstate[NUMBUTTONS];
static byte currentstate[NUMBUTTONS];
byte index;
for (index = 0; index < NUMBUTTONS; index++) {
currentstate[index] = digitalRead(buttons[index]); // read the button
/*Serial.print(index, DEC);
Serial.print(": cstate=");
Serial.print(currentstate[index], DEC);
Serial.print(", pstate=");*/
Serial.print(previousstate[index], DEC);
Serial.print(", press=");
if (currentstate[index] == previousstate[index]) {
if ((pressed[index] == LOW) && (currentstate[index] == LOW)) {
// just pressed
justpressed[index] = 1;
}
else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) {
// just released
justreleased[index] = 1;
}
pressed[index] = !currentstate[index]; // remember, digital HIGH means NOT pressed
}
//Serial.println(pressed[index], DEC);
previousstate[index] = currentstate[index]; // keep a running tally of the buttons
}
}
void loop() {
byte i;
delay(200);
if (justpressed[0]) {
justpressed[0] = 0;
playfile("SOUND1.WAV");
}
else if (justpressed[1]) {
justpressed[1] = 0;
playfile("SOUND2.WAV");
}
else if (justpressed[2]) {
justpressed[2] = 0;
playfile("SOUND3.WAV");
}
else if (justpressed[3]) {
justpressed[3] = 0;
playfile("SOUND4.WAV");
}
else if (justpressed[4]) {
justpressed[4] = 0;
playfile("SOUND5.WAV");
}
else if (justpressed[5]) {
justpressed[5] = 0;
playfile("SOUND6.WAV");
}
else if (justpressed[6]) {
justpressed[6] = 0;
playfile("SOUND7.WAV");
}
else if (justpressed[7]) {
justpressed[7] = 0;
playfile("SOUND8.WAV");
}
else if (justpressed[8]) {
justpressed[8] = 0;
playfile("SOUND9.WAV");
}
else if (justpressed[9]) {
justpressed[9] = 0;
playfile("SOUND10.WAV");
}
else if (justpressed[10]) {
justpressed[10] = 0;
playfile("SOUND11.WAV");
}
else if (justpressed[11]) {
justpressed[11] = 0;
playfile("SOUND12.WAV");
}
else if (justpressed[12]) {
justpressed[12] = 0;
playfile("SOUND13.WAV");
}
else if (justpressed[13]) {
justpressed[13] = 0;
playfile("SOUND14.WAV");
}
else if (justpressed[14]) {
justpressed[14] = 0;
playfile("SOUND15.WAV");
}
else if (justpressed[15]) {
justpressed[15] = 0;
playfile("SOUND16.WAV");
}
else if (justpressed[16]) {
justpressed[16] = 0;
playfile("SOUND17.WAV");
}
else if (justpressed[17]) {
justpressed[17] = 0;
playfile("SOUND18.WAV");
}
else if (justpressed[18]) {
justpressed[18] = 0;
playfile("SOUND19.WAV");
}
else if (justpressed[19]) {
justpressed[19] = 0;
playfile("SOUND20.WAV");
}
}
// Plays a full file from beginning to end with no pause.
void playcomplete(char *name) {
// call our helper to find and play this name
playfile(name);
while (wave.isplaying) {
// do nothing while its playing
}
// now its done playing
}
void playfile(char *name) {
// see if the wave object is currently doing something
if (wave.isplaying) {// already playing something, so stop it!
wave.stop(); // stop it
}
// look in the root directory and open the file
if (!f.open(root, name)) {
putstring("Couldn't open file "); Serial.print(name); return;
}
// OK read the file and turn it into a wave object
if (!wave.create(f)) {
putstring_nl("Not a valid WAV"); return;
}
// ok time to play! start playback
wave.play();
}
- adafruit_support_bill
- Posts: 88086
- Joined: Sat Feb 07, 2009 10:11 am
Re: Waveshield + Arduino Mega -> Distorted sound
So you are still using the interrupt to check the switches. That will be generating serial output faster than it can be transmitted. That explains the freezing.
What happens if you comment out the interrupt code and move the check_switches to the loop?
What happens if you comment out the interrupt code and move the check_switches to the loop?
- dy-wen
- Posts: 30
- Joined: Wed Sep 16, 2009 11:31 am
Re: Waveshield + Arduino Mega -> Distorted sound
Hey
It took me a while to respond, because everything I tried, I ran into big red compilation errors. Part of the problem was me taking your instructions to literally (I really tried to move the whole code of check_switches into the loop -> whilst just moving check_switches itself was enough.)
Two amateur coders together (someone else and me ) found out more about the timer aspect added to the code:
--> This is what I found out about this timer: http://www.uchobby.com/index.php/2007/1 ... nterrupts/ -> it uses pwm ports -> which would really explain the noise (hm or not? would it be better to use timer1? - I'm too newbie for this).
A visit to the Brussels Hackerspace https://hackerspace.be where I met the pro-coder Leandro, someone who can read and write , actually solved the noise problem.
Here are some screenshots of the differences (of the original code and the changed code):
Taking out the timer: Moving check_switches to the loop and adding delay: Final code: complete:
I do realize why the timer was in there. When you don't use buttons for a while, and you push one, it is not "awake" immediately, a part of the sound gets cut. I'll do some fiddling with the delay time - see to where I can push it.
Thanks a lot for your patience -> I'll give a little sign to the guy who's writing code for the waveshield library.
Tomorrow (!!) I'm installing this in an interactive map/sound installation with stories: http://www.constantvzw.org/site/Stitchi ... reNUM.html
It took me a while to respond, because everything I tried, I ran into big red compilation errors. Part of the problem was me taking your instructions to literally (I really tried to move the whole code of check_switches into the loop -> whilst just moving check_switches itself was enough.)
Two amateur coders together (someone else and me ) found out more about the timer aspect added to the code:
Code: Select all
TCCR2A = 0;
TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;
//Timer2 Overflow Interrupt Enable
TIMSK2 |= 1<<TOIE2;
}
SIGNAL(TIMER2_OVF_vect) {
check_switches();
}
A visit to the Brussels Hackerspace https://hackerspace.be where I met the pro-coder Leandro, someone who can read and write , actually solved the noise problem.
Here are some screenshots of the differences (of the original code and the changed code):
Taking out the timer: Moving check_switches to the loop and adding delay: Final code: complete:
Code: Select all
#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"
SdReader card; // This object holds the information for the card
FatVolume vol; // This holds the information for the partition on the card
FatReader root; // This holds the information for the filesystem on the card
FatReader f; // This holds the information for the file we're play
WaveHC wave; // This is the only wave (audio) object, since we will only play one at a time
#define DEBOUNCE 5 // button debouncer
// here is where we define the buttons that we'll use. button "1" is the first, button "6" is the 6th, etc
byte buttons[] = {22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41};
// This handy macro lets us determine how big the array up above is, by checking the size
#define NUMBUTTONS sizeof(buttons)
// we will track if a button is just pressed, just released, or 'pressed' (the current state
volatile byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];
// this handy function will return the number of bytes currently free in RAM, great for debugging!
int freeRam(void)
{
extern int __bss_end;
extern int *__brkval;
int free_memory;
if((int)__brkval == 0) {
free_memory = ((int)&free_memory) - ((int)&__bss_end);
}
else {
free_memory = ((int)&free_memory) - ((int)__brkval);
}
return free_memory;
}
void sdErrorCheck(void)
{
if (!card.errorCode()) return;
putstring("\n\rSD I/O error: ");
Serial.print(card.errorCode(), HEX);
putstring(", ");
Serial.println(card.errorData(), HEX);
while(1);
}
void setup() {
byte i;
// set up serial port
Serial.begin(9600);
Serial.print("WaveHC with ");
Serial.print(NUMBUTTONS, DEC);
putstring_nl(" buttons");
putstring("Free RAM: "); // This can help with debugging, running out of RAM is bad
Serial.println(freeRam()); // if this is under 150 bytes it may spell trouble!
// Set the output pins for the DAC control. This pins are defined in the library
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
// pin13 LED
pinMode(13, OUTPUT);
// Make input & enable pull-up resistors on switch pins
for (i=0; i< NUMBUTTONS; i++) {
pinMode(buttons[i], INPUT);
digitalWrite(buttons[i], HIGH);
}
// if (!card.init(true)) { //play with 4 MHz spi if 8MHz isn't working for you
if (!card.init()) { //play with 8 MHz spi (default faster!)
putstring_nl("Card init. failed!"); // Something went wrong, lets print out why
sdErrorCheck();
while(1); // then 'halt' - do nothing!
}
// enable optimize read - some cards may timeout. Disable if you're having problems
card.partialBlockRead(true);
// Now we will look for a FAT partition!
uint8_t part;
for (part = 0; part < 5; part++) { // we have up to 5 slots to look in
if (vol.init(card, part))
break; // we found one, lets bail
}
if (part == 5) { // if we ended up not finding one :(
putstring_nl("No valid FAT partition!");
sdErrorCheck(); // Something went wrong, lets print out why
while(1); // then 'halt' - do nothing!
}
// Lets tell the user about what we found
putstring("Using partition ");
Serial.print(part, DEC);
putstring(", type is FAT");
Serial.println(vol.fatType(),DEC); // FAT16 or FAT32?
// Try to open the root directory
if (!root.openRoot(vol)) {
putstring_nl("Can't open root dir!"); // Something went wrong,
while(1); // then 'halt' - do nothing!
}
// Whew! We got past the tough parts.
putstring_nl("Ready!");
}
void check_switches()
{
static byte previousstate[NUMBUTTONS];
static byte currentstate[NUMBUTTONS];
byte index;
for (index = 0; index < NUMBUTTONS; index++) {
currentstate[index] = digitalRead(buttons[index]); // read the button
/*Serial.print(index, DEC);
Serial.print(": cstate=");
Serial.print(currentstate[index], DEC);
Serial.print(", pstate=");
Serial.print(previousstate[index], DEC);
Serial.print(", press=");*/
if (currentstate[index] == previousstate[index]) {
if ((pressed[index] == LOW) && (currentstate[index] == LOW)) {
// just pressed
justpressed[index] = 1;
}
else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) {
// just released
justreleased[index] = 1;
}
pressed[index] = !currentstate[index]; // remember, digital HIGH means NOT pressed
}
//Serial.println(pressed[index], DEC);
previousstate[index] = currentstate[index]; // keep a running tally of the buttons
}
}
void loop() {
byte i;
check_switches();
delay(200);
if (justpressed[0]) {
justpressed[0] = 0;
playfile("SOUND1.WAV");
}
else if (justpressed[1]) {
justpressed[1] = 0;
playfile("SOUND2.WAV");
}
else if (justpressed[2]) {
justpressed[2] = 0;
playfile("SOUND3.WAV");
}
else if (justpressed[3]) {
justpressed[3] = 0;
playfile("SOUND4.WAV");
}
else if (justpressed[4]) {
justpressed[4] = 0;
playfile("SOUND5.WAV");
}
else if (justpressed[5]) {
justpressed[5] = 0;
playfile("SOUND6.WAV");
}
else if (justpressed[6]) {
justpressed[6] = 0;
playfile("SOUND7.WAV");
}
else if (justpressed[7]) {
justpressed[7] = 0;
playfile("SOUND8.WAV");
}
else if (justpressed[8]) {
justpressed[8] = 0;
playfile("SOUND9.WAV");
}
else if (justpressed[9]) {
justpressed[9] = 0;
playfile("SOUND10.WAV");
}
else if (justpressed[10]) {
justpressed[10] = 0;
playfile("SOUND11.WAV");
}
else if (justpressed[11]) {
justpressed[11] = 0;
playfile("SOUND12.WAV");
}
else if (justpressed[12]) {
justpressed[12] = 0;
playfile("SOUND13.WAV");
}
else if (justpressed[13]) {
justpressed[13] = 0;
playfile("SOUND14.WAV");
}
else if (justpressed[14]) {
justpressed[14] = 0;
playfile("SOUND15.WAV");
}
else if (justpressed[15]) {
justpressed[15] = 0;
playfile("SOUND16.WAV");
}
else if (justpressed[16]) {
justpressed[16] = 0;
playfile("SOUND17.WAV");
}
else if (justpressed[17]) {
justpressed[17] = 0;
playfile("SOUND18.WAV");
}
else if (justpressed[18]) {
justpressed[18] = 0;
playfile("SOUND19.WAV");
}
else if (justpressed[19]) {
justpressed[19] = 0;
playfile("SOUND20.WAV");
}
}
// Plays a full file from beginning to end with no pause.
void playcomplete(char *name) {
// call our helper to find and play this name
playfile(name);
while (wave.isplaying) {
// do nothing while its playing
}
// now its done playing
}
void playfile(char *name) {
// see if the wave object is currently doing something
if (wave.isplaying) {// already playing something, so stop it!
wave.stop(); // stop it
}
// look in the root directory and open the file
if (!f.open(root, name)) {
putstring("Couldn't open file "); Serial.print(name); return;
}
// OK read the file and turn it into a wave object
if (!wave.create(f)) {
putstring_nl("Not a valid WAV"); return;
}
// ok time to play! start playback
wave.play();
}
Thanks a lot for your patience -> I'll give a little sign to the guy who's writing code for the waveshield library.
Tomorrow (!!) I'm installing this in an interactive map/sound installation with stories: http://www.constantvzw.org/site/Stitchi ... reNUM.html
- adafruit_support_bill
- Posts: 88086
- Joined: Sat Feb 07, 2009 10:11 am
Re: Waveshield + Arduino Mega -> Distorted sound
Great that you got it working!
The delay was a simple way to get rid of the noise, but neither the timer nor the delay are optimal solutions. The best way to do it is with 'pin-change interrupts' that generate an interrupt only when a button is pressed. That will keep your buttons responsive, without having to check them thousands of times per second. http://www.arduino.cc/playground/Main/PinChangeIntI do realize why the timer was in there. When you don't use buttons for a while, and you push one, it is not "awake" immediately, a part of the sound gets cut.
- dy-wen
- Posts: 30
- Joined: Wed Sep 16, 2009 11:31 am
Re: Waveshield + Arduino Mega -> Distorted sound
sweet!
and..
sweat...
If I understand it correctly (the context is giving me the meaning), this library is for regular Arduino's:
and..
sweat...
If I understand it correctly (the context is giving me the meaning), this library is for regular Arduino's:
--> whilst http://arduino.cc/en/Main/ArduinoBoardMegaThe PinChangeInt effort runs in the other direction, with clarity sacrificed for the highest performance. To that end, this implementation can handle a 4.5 KHz input signal (with a 1 KHz timer running as well) on an 8 MHz ATMega328, with significant code in both the timer and pin change interrupt handlers.
Brain.. hurts..Summary
Microcontroller ATmega1280
Operating Voltage 5V
Input Voltage (recommended) 7-12V
Input Voltage (limits) 6-20V
Digital I/O Pins 54 (of which 14 provide PWM output)
Analog Input Pins 16
DC Current per I/O Pin 40 mA
DC Current for 3.3V Pin 50 mA
Flash Memory 128 KB of which 4 KB used by bootloader
SRAM 8 KB
EEPROM 4 KB
Clock Speed 16 MHz
- adafruit_support_bill
- Posts: 88086
- Joined: Sat Feb 07, 2009 10:11 am
Re: Waveshield + Arduino Mega -> Distorted sound
Sorry, forgot you were on the Mega
I'm having trouble accessing the Arduino site at the moment, but if you search, I'm sure that somebody has done pin-change interrupts on the Mega as well.
I'm having trouble accessing the Arduino site at the moment, but if you search, I'm sure that somebody has done pin-change interrupts on the Mega as well.
- dy-wen
- Posts: 30
- Joined: Wed Sep 16, 2009 11:31 am
Re: Waveshield + Arduino Mega -> Distorted sound
Hey
No problemo
I have made a bad observation --> in a previous post I reply that the delay option sometimes bites off the beginning of the sound -> but this is not the case! I was using fancy Phonic active monitor speakers, which was set on the special option of "auto-on"
( http://www.phonic.com/images/detailed/p ... f79390.jpg )
This was actually what was gnawing off the beginning minutes of the sound!
Now, I do wonder whether this sketch, using the delay, could become problematic. Will it uhm, disintegrate? Do damage? Stop working?
PinChangeInt is better - because it's more stable?
Going abstract here
Greetz and big thanks
No problemo
I have made a bad observation --> in a previous post I reply that the delay option sometimes bites off the beginning of the sound -> but this is not the case! I was using fancy Phonic active monitor speakers, which was set on the special option of "auto-on"
( http://www.phonic.com/images/detailed/p ... f79390.jpg )
This was actually what was gnawing off the beginning minutes of the sound!
Now, I do wonder whether this sketch, using the delay, could become problematic. Will it uhm, disintegrate? Do damage? Stop working?
PinChangeInt is better - because it's more stable?
Going abstract here
Greetz and big thanks
- adafruit_support_bill
- Posts: 88086
- Joined: Sat Feb 07, 2009 10:11 am
Re: Waveshield + Arduino Mega -> Distorted sound
The delay won't hurt anything. If it isn't broken, there is no need to fix it . Interrupts are just a more elegant and responsive solution.
Please be positive and constructive with your questions and comments.