Hello Joop,
Very interested in this project.
I just started to use the uno and am exploring the possibilities.
Gerard
Very interested in this project.
I just started to use the uno and am exploring the possibilities.
Gerard
//------------------------------------------------------------------------------
// Arduino PI Firmware
//------------------------------------------------------------------------------
// This project uses the Arduino Uno
// Clock is run off the internal 16MHz oscillator
// Each instruction takes 1 clock cycles so time resolution is 0.0625us
// Timer2 controls the main loop, has 8 bits plus prescaler.
// Timer1 controls delays, has 16 bits plus prescaler.
// a bit of history:
// version 1.0 - published jan 29, 2013 using standard Arduino commands, shortest
// delay possible because of this is about 15 microseconds
// version 1.1 - published feb 03, 2013 replace all of the digitalWrite command
// with direct port access, shortest delay below 1 microsecond
// version 1.2 - published mar 02, 2015 with rotary encoder support instead pot on A5
// code rotary encoder example from bildr article: http://bildr.org/2012/08/rotary-encoder-arduino/
//--- Defines ---
#define DIGITAL_OUT PORTB
#define TX_PIN 5 // PB5 or D13
#define SAMPLE_PIN 4 // PB4 or D13
#define PWM_PIN 3 // PB3 or D11
#define period 47 // 255-208 -> 1664us (~600 Hz)
#define TxPulseWidth 63935 // 65535 - 1600 -> 100 uS
#define SampleWidth 65295 // 65535 - 240 -> 15 uS
#define AudioDelay 65135 // 65535 - 400 -> 25 uS
#define AudioWidth 62335 // 65535 - 3200 -> 200 uS
//--- Variables ---
unsigned int Sample1Delay = 65535-240; // 15us
//these pins can not be changed 2/3 are special pins
int encoderPin1 = 2; // D2 and D3 ar used to read encoder
int encoderPin2 = 3;
volatile int lastEncoded = 0;
volatile long encoderValue = 0;
long lastencoderValue = 0;
int lastMSB = 0;
int lastLSB = 0;
//------------------------------------------------------------------------------
// Initialization routines
// Initialize the I/O pins and set some flags
//
void Init (void)
{
DDRB = B00111111; // set PORTB (digital 13-8 to outputs
TCCR0A = 0; // disable timer0
TCCR0B = 0;
}
// Timer2 is 8 bits with Div128, so delay is (255-n)*128/Fosc
// For Fosc = 16MHz Timer2 has 8us of resolution
void InitTimer2 (void)
{
TCCR2A = 0;
TCCR2B = 0;
bitSet (TIMSK2, TOIE2); // Enable Timer2 interrupt
TCCR2B = 0x05; // Prescaler = /128 (8 us resolution)
}
// Timer1 is 16 bits and clocked at 16MHz; use PS=1 for 0.0625us resolution
//
void InitTimer1 (void)
{
TCCR1A = 0;
TCCR1B = 0;
bitClear (TIMSK1, TOIE1); // Don't allow an interrupt
TCNT1 = 0; // Clear the timer
TCCR1B = 0x01; // Prescaler = /1 (62.5ns resolution)
}
//Rotary encoder read
void updateEncoder(){
int MSB = digitalRead(encoderPin1); //MSB = most significant bit
int LSB = digitalRead(encoderPin2); //LSB = least significant bit
int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
int sum = (lastEncoded << 2) | encoded; //adding it to the previous encoded value
if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;
if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --;
lastEncoded = encoded; //store this value for next time
}
void setup ()
{
Init ();
InitTimer2 ();
InitTimer1 ();
TCNT2 = 200; // Set the timer
//Code for rotary encoder
pinMode(encoderPin1, INPUT);
pinMode(encoderPin2, INPUT);
digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
digitalWrite(encoderPin2, HIGH); //turn pullup resistor on
//call updateEncoder() when any high/low changed seen
//on interrupt 0 (pin 2), or interrupt 1 (pin 3)
attachInterrupt(0, updateEncoder, CHANGE);
attachInterrupt(1, updateEncoder, CHANGE);
}
//------------------------------------------------------------------------------
// Processing routines
// Delay (in us) = 65535-n
// Because of the fudge factor, ~0.75us is the minimum delay.
//
void Timer1Delay (unsigned int n)
{
n += 12; // Adjust for fixed error (approx 0.75us)
TCNT1 = n; // Load the counter
bitSet (TIFR1, TOV1); // Clear the flag
while (!(TIFR1 & (1<<TOV1))) {
;
} // Wait for a flag
}
// Read the pulse delay Rotary Encoder
//
void ReadDelayEnc (void)
{
static int value;
Sample1Delay = 65535 - 12 - encoderValue; // about 0.75us min, 64us max
}
// ISR() is the interrupt service routine for Timer2. The main loop is
// triggered off this interrupt and must be completed before the next
// interrupt.
ISR (TIMER2_OVF_vect)
{
TCNT2 = period; // Reset the timer
DIGITAL_OUT |= (1<<TX_PIN);
Timer1Delay (TxPulseWidth); // Transmit pulse
DIGITAL_OUT &= ~(1<<TX_PIN);
Timer1Delay (Sample1Delay); // TX-to-sample pulse delay
DIGITAL_OUT |= (1<<SAMPLE_PIN);
Timer1Delay (SampleWidth); // Sample pulse
DIGITAL_OUT &= ~(1<<SAMPLE_PIN);
Timer1Delay (AudioDelay); // Delay for audio
DIGITAL_OUT |= (1<<PWM_PIN);
Timer1Delay(AudioWidth); // Speaker pulse
DIGITAL_OUT &= ~(1<<PWM_PIN);
ReadDelayEnc();
// The remaining routines are where extra processing gets done. It is critical
// that all processing is complete before the next TCNT0 interrupt occurs, which
// depends on the TX pulse rate, TX pulse width, and sampling time. If the pulse
// rate = 600Hz, pulse width = 100us, and max sampling time = 35us then the
// processing time available is 1667us - 100us - 35us = 1532us. With a 16MHz
// clock we have an instruction cycle of 0.0625us, so there is time for 24512 code
// instructions, including calls and returns.
}
void loop ()
{
}

Comment