freezing problem, Cookbook ch. 1.6 p. 20

Hello. This is my first post. I did a project in the Cookbook, chapter 1.6, p. 20. (LDR controls speaker pitch. Two questions:

  1. When it goes dark, the speaker makes a pitch that quickly rises, then stops making sound. Hitting the reset button makes it run okay again, as long as the lights are on. Why?

  2. The pitch seems to be more "stepwise" than I expected. I was hoping for a more smoothly-moving pitch change. Why?

Thanks

Can you paste your code here please? Put it in code tags.

You can do that by hitting the # button above the posting area.

//from Arduino Cookbook by Michael Margolis: ch.1.6 p. 20

//for some reason, when the lights went out, the speaker went too high and stopped making sound.  Had to press reset button to resume.

const int outputPin = 9; //Speaker connected to digital pin 9
const int sensorPin = 0;  //connect sensor to analog input 0

const int minDuration = 1;  //1ms on, 1ms off (500 Hz)
const int maxDuration = 10;  //10ms on, 10 ms off (50 Hz)

void setup ()
{
  pinMode(outputPin, OUTPUT); //enable output on the led pin
}
void loop()
{
  int sensorReading = analogRead(sensorPin);  //read the analog input
  int rate = map(sensorReading, 200, 800, minDuration, maxDuration);
  
 digitalWrite(outputPin, HIGH); //set the LED on
  delay(rate); //wait duration dependent on light level
  digitalWrite(outputPin, LOW); //set the LED off
  delay(rate);
}

What sort of speaker? How is it connected to the Arduino?

I can’t answer your first question. I made the same setup with my UNO and experienced the same issue.

But this code is designed for a LED. A speaker needs only a instantaneous pulse of voltage. So you don’t need the first delay.

digitalWrite(outputPin, HIGH); //set the LED on
delay(rate); //wait duration dependent on light level ---- get rid of this line.
digitalWrite(outputPin, LOW); //set the LED off
delay(rate);

You want it on then off as quick as possible.

I played around with the code a bit and added a calibration in the setup. For the first five seconds the program will be calibrating so during that time expose the photo cell to min and max light levels and those values will be stored and later any further reads will be constrained between them. Also the ms delay is too slow, use us delay for a better range of tones from the buzzer.

// 5v - photocell - sensorPin - 1k resistor - ground


const int outputPin = 9; //Speaker connected to digital pin 9
const int sensorPin = 0;  //connect sensor to analog input 0

const int minDuration = 100;  
const int maxDuration = 5000; 

int sensorReading = 0;         // the sensor value
int sensorMin = 1023;  // minimum sensor value
int sensorMax = 0;     // maximum sensor value


void setup ()
{
  pinMode(outputPin, OUTPUT); //enable output on the led pin
  
  // calibrate during the first five seconds 
  while (millis() < 5000) {
    sensorReading = analogRead(sensorPin);

    // record the maximum sensor value
    if (sensorReading > sensorMax) {
      sensorMax = sensorReading;
    }

    // record the minimum sensor value
    if (sensorReading < sensorMin) {
      sensorMin = sensorReading;
    }
  }

}
void loop()
{
  sensorReading = analogRead(sensorPin);  //read the analog input
  sensorReading = constrain(sensorReading, sensorMin, sensorMax);
  int rate = map(sensorReading, sensorMin, sensorMax, minDuration, maxDuration);
  
  digitalWrite(outputPin, HIGH); //set the LED on
  digitalWrite(outputPin, LOW); //set the LED off
  delayMicroseconds(rate);
}

Hi. Thanks for helping a beginner out. The speakers I used were a 1.5" Walkman headphone and a 3" paper cone speaker.

I just reviewed the code I posted below and see that I left out a line; after the int rate line I should have had:

rate = constrain(rate, minDuration, maxDuration);

When I get home I'll check the effect of having left it out. Also, RacerX89, thanks for the modified code. I'll try it out too.

Yea I experience the same glitch if I leave out the constrain function.

I just tried the code you posted. The sound seems to move more smoothly between notes, like a theremin now. Thanks. Now I'll have to look at the code and see if I can understand why.

If I understand the int data type, I think I have an explanation for why the sound moves from note to note stepwise rather than in a smooth glissando. Tell me if this sounds feasible:

The variable declaration of int sensorReading = analogRead(sensorPin); takes an analog value and rounds it to an integer. Also, the map function only produces integer results.

The frequencies of the speaker, therefore, are forced to jump between frequencies determined by integers rather than analog values.

Sound right?

The variable declaration of int sensorReading = analogRead(sensorPin); takes an analog value and rounds it to an integer.

analogRead returns an "int" so there's no rounding involved.

It’s more likely to me that the time taken to do the read would affect it. Each analogRead takes 104 uS, so while you are turning the knob, you are taking discrete readings, not continuous ones.

Plus, once you have a reading you do:

delayMicroseconds(rate);

During that delay no further readings are being taken.