Show Posts
Pages: [1]
1  Using Arduino / Audio / Arduino playing audio .wav file with PWM and external eprom IC on: January 11, 2013, 12:30:48 am
The idea is to incorporate voice in MCU project. I've found a good example, modified little to use with my ATmega8 and it's working with data sample stored in MCU. But as I need more space (upto 5 sec. of msg.), I want to use external eprom (24c512 is handy to me & sufficient for my sample).

I've burn eprom with voice sample (8 Mhz, 8bit) & trying to run with the below code. Though I can't get any result (No voice, No led blink in place of speaker, No serial output when using serial monitor)  ! I only assume that the eprom can't response in such a fast ISR/interrupt ?? Pl. tell me if any solution to this problem.

// ATMega8, 16Mhz., EPROM 24C512

 * based on speaker_pcm
 * EPROM Library from :
#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <Wire.h>
#include <EEPROM24LC256_512.h>

#define SAMPLE_RATE 8000
unsigned int sounddata_length=65000;
int ledPin = 13;
int speakerPin = 11;
volatile uint16_t sample;
byte lastSample;

//define eeprom chip (1 per chip)
EEPROM256_512 mem_2;

// This is called at 8000 Hz to load the next sample.
    if (sample >= sounddata_length) {
        if (sample == sounddata_length + lastSample) {
            stopPlayback(); }
        else {
            // Ramp down to zero to reduce the click at the end of playback.
            OCR2 = sounddata_length + lastSample - sample; }
    else {
        OCR2 = mem_2.readByte(sample);

void startPlayback()
pinMode(speakerPin, OUTPUT);

    // Set up Timer 2 to do pulse width modulation on the speaker pin.
    ASSR &= ~(_BV(AS2));

    // Set fast PWM mode
    TCCR2 = _BV(WGM21) | _BV(WGM20);
    TCCR2 = (TCCR2 & ~(_BV(COM20))) | _BV(COM21) ;
    TCCR2 = (TCCR2 & ~(_BV(CS22) | _BV(CS21))) | _BV(CS20);
    //Serial.println("Starting, Please wait...");

    // Set initial pulse width to the first sample.
    OCR2 = mem_2.readByte(0);

    // Set up Timer 1 to send a sample every interrupt.

    // Set CTC mode (Clear Timer on Compare Match)
    // Have to set OCR1A *after*, otherwise it gets reset to 0!
    TCCR1B = (TCCR1B & ~_BV(WGM13)) | _BV(WGM12);
    TCCR1A = TCCR1A & ~(_BV(WGM11) | _BV(WGM10));

    // No prescaler
    TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);

    // Set the compare register (OCR1A).
    // OCR1A is a 16-bit register, so we have to do this with
    // interrupts disabled to be safe.
    OCR1A = F_CPU / SAMPLE_RATE;    // 16e6 / 8000 = 2000

    // Enable interrupt when TCNT1 == OCR1A (p.136)
    TIMSK |= _BV(OCIE1A);

    lastSample = mem_2.readByte(sounddata_length-1);
    sample = 0;

void stopPlayback()
    // Disable playback per-sample interrupt.
    TIMSK &= ~_BV(OCIE1A);
    // Disable the per-sample timer completely.
    TCCR1B &= ~_BV(CS10);
    // Disable the PWM timer.
    TCCR2 &= ~_BV(CS20);
    digitalWrite(speakerPin, LOW);

void setup()
    pinMode(ledPin, OUTPUT);

void loop()
{ while (true); }

Used external EPROM lib., it's tested & working fine.
2  Using Arduino / Programming Questions / IR Phototransistor pair interrupt problem on: October 30, 2012, 12:05:14 am
I've salvage some ir-photo pair, I want to make rotary encoder as inside the mouse. The purpose is to length/distance measurement using rotary wheel movement.

my circuit is

The problem is when I try the code, the tick count is not reliable when moving rotary wheel faster. Though slow but constant movement gives correct output.

Some other question.

  • Rotary wheel encoder is reliable for correct x/y movement ?
  • When breaking the IR beam (put something between the ir-photo pair) fast or slow, the counts increments more than one.
  • How to achieve high resolution count accurately with these type of encoders

Here is my code, I've try different interrupt mode and also moving count var to main loop but the problem exists.


#define encoder0PinA 2
//#define encoder0PinB 4

volatile unsigned int encoder0Pos = 0;
static boolean rotating=false;

void setup() {
  pinMode(encoder0PinA, INPUT);
  digitalWrite(encoder0PinA, HIGH);
  //pinMode(encoder0PinB, INPUT);
  //digitalWrite(encoder0PinB, HIGH);

  attachInterrupt(0, rotEncoder, FALLING); 
  Serial.begin (9600);

void rotEncoder(){
  // If a signal change (noise or otherwise) is detected
  // in the rotary encoder, the flag is set to true

void loop() {
  if (rotating) {
    // When signal changes we wait 2 milliseconds for it to
    // stabilise before reading (increase this value if there
    // still bounce issues)
    rotating=false; // Reset the flag back to false

Above code is from with little bit of change. This is testing project only, so want to use only one encoder.

Pages: [1]