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