Absolute Encoder module. More...
Go to the source code of this file.
Functions | |
| int | ae_get_pos (AE_ID encoder_id) |
| Returns the position of the given encoder. | |
| void | ae_init_encoder (AE_ID encoder_id, int zero, int rpm, int cpr) |
| Initializes an encoder. | |
| void | ae_isr (void) |
| The interrupt service routine for the absolute encoder module. | |
| static void | ae_read (AE_ID encoder_id) |
| Reads in the data for the given encoder. | |
| void | ae_update (void) |
| Updates the absolute encoder data. | |
| void | ae_wait (void) |
| Blocks until the current encoder update is complete. | |
Variables | |
| static volatile AE_ID | ae_current_encoder |
| The current encoder data is being read from. | |
| static AE_ENCODER | ae_encoders [2] |
| Currently only using two encoders. | |
| static volatile AE_STATUS | ae_status = AE_DONE |
| The status of the absolute encoder module. | |
Absolute Encoder module.
Reads from two magnetic encoders. For each call to ae_update, all encoders set by ae_init_encoder_* are read from.
Make sure to call ae_init_encoder_* (* = 1 or 2) for the encoders you wish to use. Then call ae_update from every row of the schedule.
B2A_MC: J3 = encoder 1 J9 = encoder 2
Example Hardware and Register Setup:
// ******************************************************************************* // SPI0 Setup for Absolute Encoder // ******************************************************************************* //Set Pinsel bits for controlling SPI0: PINSEL0 &= ~(3<<8); //clear pin P0.4 PINSEL0 &= ~(3<<10); //clear pin P0.5 PINSEL0 &= ~(3<<26); //clear pin P0.5 PINSEL0 |= (1<<8); //SCKO for SPI0 (clock for data transfer) PINSEL0 |= (1<<10); //MISO for SPI0 (master in slave out data) PINSEL0 |= (0<<26); //set P0_13 to GPIO -- set pin to output FIO0DIR |= (1<<13); //this pin controls multiplexers (SN74LVC1G3157) via the SN74LVC1G07 level shitfer //when P0_13 is low J3 encoder can be read via SPI //when '' is high J9 encoder can be read //Set Up SPI Register: S0SPCR |= (1<<2) | (0<<8) | (1<<9) | (1<<10) | (1<<11); //recieve 14 bits of data S0SPCR |= (1<<4); //set clock polarity to active low S0SPCR |= (1<<5); //activate master mode S0SPCCR = 60; //set data transfer rate; PCLK / S0SPCCR = 60MHz / 60 = 1MHz
The isr ae_isr will also need to be setup:
// ************ PRIORITY 10 ****************** //Absolute Encoder VICVectAddr10 = (unsigned long)ae_isr; VICVectCntl10 = 0x20 | VIC_SPI0; VICIntEnable = 1 << VIC_SPI0;
Definition in file abs_enc.c.
| int ae_get_pos | ( | AE_ID | encoder_id | ) |
Returns the position of the given encoder.
Position = data - zero_offset.
| encoder_id | The encoder to read from, either AE_1 (J3) or AE_2 (J9). |
Definition at line 116 of file abs_enc.c.
References error_occurred(), AE_ENCODER::value, and AE_ENCODER::zero.
00117 { 00118 if (encoder_id < AE_LAST){ //valid encoder id 00119 AE_ENCODER* encoder = &(ae_encoders[encoder_id]); 00120 return encoder->value - encoder->zero; 00121 } else { 00122 error_occurred(ERROR_AE_INVALID_ID); 00123 return 0; 00124 } 00125 }
| void ae_init_encoder | ( | AE_ID | encoder_id, | |
| int | zero, | |||
| int | rpm, | |||
| int | cpr | |||
| ) |
Initializes an encoder.
Call this for each encoder you wish to use.
| encoder_id | The id of the encoder to initialize. | |
| zero | The zero offset for the encoder. Check what this by starting with it at zero, then moving the shaft to the desired zero position. The output at that position should be the zero. | |
| rpm | The max rpm of the shaft the encoder is attached to. | |
| cpr | The counts per revolution of the encoder. |
Definition at line 65 of file abs_enc.c.
References AE_ENCODER::delta, error_occurred(), AE_ENCODER::read, AE_ENCODER::value, and AE_ENCODER::zero.
00065 { 00066 if (encoder_id < AE_LAST){ 00067 AE_ENCODER* encoder = &(ae_encoders[encoder_id]); 00068 encoder->read = 1; 00069 encoder->value = 0; 00070 encoder->zero = zero; 00071 encoder->delta = (int)((float)rpm * (float)cpr / (60.0 * 1000.0 * SCHED_SPEED)) + 5; 00072 } else { 00073 error_occurred(ERROR_AE_INVALID_ID); 00074 } 00075 }
| void ae_isr | ( | void | ) |
The interrupt service routine for the absolute encoder module.
When one encoder has completed its readout, causes an interrupt which will read the data in software.
Definition at line 140 of file abs_enc.c.
References ae_current_encoder, ae_read(), ae_status, AE_ENCODER::delta, error_occurred(), and AE_ENCODER::value.
00141 { 00142 int int_state = S0SPSR; 00143 int new_data; 00144 AE_ENCODER* enc; 00145 00146 S0SPINT = 1; //clear interrupt flag in SPI register 00147 00148 // ***** READ NEW DATA ***** // 00149 enc = &(ae_encoders[ae_current_encoder]); 00150 new_data = S0SPDR&0x1FFF; //read data from SPI 00151 //make sure data is valid 00152 if (new_data > enc->value + enc->delta){ //over bounds, limit 00153 new_data = enc->value + enc->delta; 00154 error_occurred(ERROR_AE_SPIKE); //report error 00155 } else if (new_data < enc->value - enc->delta){ //below bounds, limit 00156 new_data = enc->value - enc->delta; 00157 error_occurred(ERROR_AE_SPIKE); //report error 00158 } 00159 00160 enc->value = new_data; 00161 00162 // ***** START NEXT ENCODER, OR FINISHED ***** // 00163 if (ae_current_encoder == AE_1){ //currently reading data from encoder 1 00164 if (ae_encoders[AE_2].read){ //if also using encoder 2 00165 ae_read(AE_2); //begin read from encoder 2 00166 } else { //otherwise we were only reading from encoder 1 00167 ae_status = AE_DONE; //so we're done! 00168 S0SPCR &= ~(1<<7); //disable interrupts 00169 } 00170 } else if (ae_current_encoder == AE_2){ //currently reading data from encoder 2 00171 ae_status = AE_DONE; //always do encoder 1 then 2, so we're done! 00172 S0SPCR &= ~(1<<7); //disable interrupts 00173 } 00174 00175 VICVectAddr = 0; //acknowledge interrupt, clear vector to interrupt function 00176 }
| static void ae_read | ( | AE_ID | encoder_id | ) | [static] |
Reads in the data for the given encoder.
| encoder_id | The encoder to read from. Either AE_1 (J3) or AE_2 (J9) |
Definition at line 98 of file abs_enc.c.
References ae_current_encoder, and error_occurred().
Referenced by ae_isr(), and ae_update().
00099 { 00100 S0SPCR |= (1<<7); //enable interrupts 00101 switch (encoder_id){ 00102 case AE_1: FIO0CLR = (1<<13); break; //set P0.13 low to read from J3 00103 case AE_2: FIO0SET = (1<<13); break; //set P0.13 high to read from J9 00104 default: error_occurred(ERROR_AE_INVALID_ID); break; 00105 } 00106 ae_current_encoder = encoder_id; //we are currently waiting for data for this encoder 00107 S0SPDR = 0; //send dummy data to begin transfer 00108 }
| void ae_update | ( | void | ) |
Updates the absolute encoder data.
CALL EVERY SCHEDULE ROW. Reads from the encoders are interrupt driven. If you only want to read once, you can call ae_update, and then use ae_wait which will block until the data has been read.
Definition at line 83 of file abs_enc.c.
References ae_read(), and ae_status.
00084 { 00085 if (ae_encoders[AE_1].read){ //if reading from encoder 1 or both encoder 1 and 2 00086 ae_read(AE_1); //begin read from encoder 1 00087 ae_status = AE_NOT_DONE; 00088 } else if (ae_encoders[AE_2].read){ //if only reading from encoder 2 00089 ae_read(AE_2); //begin read from encoder 2 00090 ae_status = AE_NOT_DONE; 00091 } //not reading any encoders 00092 }
| void ae_wait | ( | void | ) |
volatile AE_ID ae_current_encoder [static] |
AE_ENCODER ae_encoders[2] [static] |
1.6.3