Laser mirroring sensor with CAN bus connection

   
     In some mechanical things with electronic control by microcontroller, needed checking position of lever arm or wheels. For this i decided use method with laser ray which mirrored from corner reflector. For my opinion corner reflector is a best practice for this device, because it reflect a ray on the same direction from it light. The same corner reflector is installed on the moon, on lunar rover for measured distance from earth to moon.
     To connect laser sensors to simple network i used CAN 2.0 interface. Microcontroller PIC18F4580 by Microchip contains integrated CAN interface which working with protocol for transmit and receive frames from units on the CAN bus, so i need only connect physical differential modulator MCP2551 to microcontroller.
      Proposed decision contains next devices:
1. Main board (green pcb on fig.) - it needed to convert messages from devices on the CAN bus to serial connection to PC
2. Laser sensor board (yellow pcb on fig.) - on this device installed laser emitted diod and photo resistor for detect reflection.
   


 
   

   To easier calculation CAN bus timing i used special application CANCULATOR by Mikroelektronika, you can download it on site mikroe.com. Displayed below part of program in language ANSI C and consist of two instances. First instance for server part (Main board) and second instance for laser sensor. Algorithm of instance provides communication for 255 devices on CAN bus.
     
Part of program for sensor device:
unsigned char Can_Init_Flags, Can_Send_Flags, Can_Rcv_Flags, CAN_Data_Len; // can flags
char CAN_Data[8], CAN_Data_Send[8], CAN_Rcvd = 0;                          // can rx/tx data buffer
char P_ID;  //
char CAN_Send_flag;
char time_puls; // Interval pulsacii ot 0 do 255; param2
char time_delay; // Vremia otsutstvia reakcii pri izmeneni vhodnogo znachenia; param3
char delta; // Raznica ot tekuschego znachenia dla fiksacii izmenenii; param4
char Algoritm_result; // rezultat raboti algoritma
const char P_TYPE = 0x01;  // Type of sensor is LAZER sensor
unsigned long CAN_Rcvd_ID;
unsigned long CAN_Send_ID;
sbit LED_Lazerdetect at RB0_bit;
sbit LED_CANactive at RB1_bit;
sbit LAZER at RB4_bit;

sbit LED_Lazerdetect_Direction at TRISB0_bit;
sbit LED_CANactive_Direction at TRISB1_bit;
sbit LAZER_Direction at TRISB4_bit;
sbit LAZER_input_Direction at TRISA1_bit;

unsigned int CAN_Send_time, ad_res, ad_res2, ad_res_accum, counter_interrupt, delay_result, time_interrupt;
char i = 0;

//======================================================================
const unsigned int SJW = 1;
const unsigned int BRP = 4;
const unsigned int PHSEG1 = 8;
const unsigned int PHSEG2 = 3;
const unsigned int PROPSEG = 8;
const unsigned int CAN_CONFIG_FLAGS =
                                       _CAN_CONFIG_SAMPLE_ONCE &
                                       _CAN_CONFIG_PHSEG2_PRG_ON &
                                       _CAN_CONFIG_XTD_MSG       &
                                       _CAN_CONFIG_DBL_BUFFER_ON &
                                       _CAN_CONFIG_VALID_XTD_MSG &
                                       _CAN_CONFIG_LINE_FILTER_OFF;
//======================================================================
//======================================================================
//********************** PROCEDURES*************************************
void interrupt(){
  
  if (PIR3.RXB0IF == 1) {                          // do we have CAN rx interrupt request?
     PIR3.RXB0IF = 0;
     BIE0.B0IE = 0;     //     Enable ECAN RX interrupt
     PIE3.RXB0IE = 0;   //     Enable ECAN RX interrupt
      LED_CANactive = !LED_CANactive;
      CAN_Rcvd = CANRead(&CAN_Rcvd_ID , CAN_Data , &CAN_Data_Len, &Can_Rcv_Flags); // receive message


      if (CAN_Rcvd_ID == 256) {CAN_Rcvd = 1;} else {CAN_Rcvd = 0; 
                                                    BIE0.B0IE = 1;     //     Enable ECAN RX interrupt
                                                    PIE3.RXB0IE = 1;}
       //     PIR3.RXB0IE = 1;                                //reenable the interrupt
      } //can interrupt

  if (INTCON.TMR0IF == 1) {INTCON.TMR0IF = 0;  //Clear the flag
                           INTCON.TMR0IE = 1;  //Reenable the interrupt
                           TMR0L = 6;         // Reset timer
                           counter_interrupt++;
                           if (CAN_Send_flag == 1) {CAN_Send_time--;}
                           
                           if (ad_res2 > delta) {time_interrupt++;
                                              if (time_interrupt > delay_result) {time_interrupt = 0;
                                                                                  Algoritm_result = ad_res2;
                                                                                  }
                                              }

                          
                          } //=================
                          
void main() {
//=========================================================================
     OSCTUNE.PLLEN = 0;   //****************************
     OSCCON.SCS1 = 1;
     OSCCON.IRCF2 = 1;    //    Internal OSC = 8MHz
     OSCCON.IRCF1 = 1;    //
     OSCCON.IRCF0 = 1;    //****************************
//=========================================================================
     Delay_ms(20);
     Read_EEPROM();
     Delay_ms(50);
//=========================================================================
     T0CON.T08BIT = 1;   // Timer in 8 bit mode
     T0CON.T0CS = 0; // Source TMR0 to internal Fosc/4
     T0CON.PSA = 0; // Prescaller enabled
     T0CON.T0SE = 0;
     T0CON.T0PS0 = 0;  // Prescaller 1:8
     T0CON.T0PS1 = 1;
     T0CON.T0PS2 = 0;
     TMR0L = 6;         // Reset timer
     T0CON.TMR0ON = 1;   // Enable timer TMR0
//=========================================================================
     BIE0.B0IE = 1;     //     Enable ECAN RX interrupt
     PIE3.RXB0IE = 1;   //     Enable ECAN RX interrupt
     INTCON.TMR0IE = 1; //      Interrupt from TMR0 eneble
     INTCON.PEIE = 1;   //
     INTCON.GIE  = 1;   // ****************************
//=========================================================================


  Can_Init_Flags = 0;                                       //
  Can_Send_Flags = 0;                                       // clear flags
  Can_Rcv_Flags  = 0;                                       //
  CAN_Rcvd = 0;
  Can_Send_Flags = _CAN_TX_PRIORITY_0 &                     // form value to be used
                   _CAN_TX_STD_FRAME &                      //     with CANWrite
                   _CAN_TX_NO_RTR_FRAME;

   
  Can_Init_Flags = _CAN_CONFIG_SAMPLE_THRICE &              // form value to be used
                   _CAN_CONFIG_PHSEG2_PRG_ON &              // with CANInit
                   _CAN_CONFIG_STD_MSG &
                   _CAN_CONFIG_DBL_BUFFER_ON &
                   _CAN_CONFIG_VALID_STD_MSG &
                   _CAN_CONFIG_LINE_FILTER_OFF;


     CANInitialize(0,30,0,0,0,Can_Init_Flags);              // Initialize CAN module 20 kbit/s
     //CANSetOperationMode(_CAN_MODE_CONFIG,0xFF);               // set CONFIGURATION mode
     //CANSetMask(_CAN_MASK_B1,-1,_CAN_CONFIG_STD_MSG);          // set all mask1 bits to ones
     //CANSetMask(_CAN_MASK_B2,-1,_CAN_CONFIG_STD_MSG);          // set all mask2 bits to ones
     CANSetOperationMode(_CAN_MODE_NORMAL,0xFF);            // set NORMAL mode
     
      /* CANInitialize(SJW, BRP, PHSEG1, PHSEG2, PROPSEG, CAN_CONFIG_FLAGS);   */
     //=========================================================================
     ADCON1.VCFG0=0;  //  Connect Vref to internal source
     ADCON1.VCFG1=0;
     LAZER_input_Direction=1; // Input AN1 as input tris
     //=========================================================================
     LED_Lazerdetect_Direction=0;
     LED_CANactive_Direction=0;
     LAZER_Direction=0;
     //=========================================================================

     //=========================================================================

     time_interrupt = 0;
     delay_result = time_delay*2;
     Algoritm_result = 0;
     CAN_Send_time = 0;
     CAN_Send_flag = 0;
     LED_Lazerdetect=0;
     LED_CANactive=0;
     LAZER=1;
     counter_interrupt = 0;
     while (counter_interrupt != 1000) {}
     LED_Lazerdetect=1;
     LED_CANactive=1;
     LAZER=0;
     counter_interrupt = 0;
     while (counter_interrupt != 1000) {}
     LED_Lazerdetect=0;
     LED_CANactive=0;
     LAZER=1;
     counter_interrupt = 0;
     while (counter_interrupt != 1000) {}
     LED_Lazerdetect=1;
     LED_CANactive=1;
     LAZER=0;
     counter_interrupt = 0;

     
     
     //*********************MAIN CYCLE******************************************
  while(1) {
if (time_puls == 0) {LAZER=1;
                            Delay_us(100);
                            ad_res = ADC_Read(1);
                            ad_res2 = ad_res >> 2;
                            if (ad_res2 < delta) {LED_Lazerdetect=0;} else {LED_Lazerdetect=1;}
                           }else{
       if (counter_interrupt == time_puls) {counter_interrupt = 0;
                                            LAZER = 1;
                                            Delay_us(100);
                                            ad_res = ADC_Read(1);
                                            ad_res2 = ad_res >> 2;
                                            LAZER = 0;
                                            if (ad_res2 < delta) {LED_Lazerdetect=0;} else {LED_Lazerdetect=1;}
                                            }
                                 }



    if (CAN_Rcvd == 1) {CAN_Rcvd = 0;

                   i = 0;
                   while (i != 8) {CAN_Data_Send[i]=0; i++;}
         if (CAN_Data[0] == 'S' && CAN_Data[1] == P_ID) {//ad_res = ADC_Read(1);
                                 CAN_Data_Send[0] = P_TYPE;
                                 CAN_Data_Send[1] = ad_res2;
                                 CAN_Data_Send[2] = time_puls;
                                 CAN_Data_Send[3] = time_delay;
                                 CAN_Data_Send[4] = delta;
                                 CAN_Data_Send[5] = Algoritm_result;
                                 //CAN_Data_Send[6] = 0;
                                 ad_res_accum = ADC_Read(2);
                                 CAN_Data_Send[7] = ad_res_accum >> 2;
                                 CAN_Send_time = 0;
                                 CAN_Send_flag = 1;

                                 }

        if (CAN_Data[0] == 'B' && P_ID == CAN_Data[1]) {INTCON.TMR0IE = 0;
                                                        if (CAN_Data[2] == 0x02) {EEPROM_Write(0x01,CAN_Data[3]);}
                                                        if (CAN_Data[2] == 0x03) {EEPROM_Write(0x02,CAN_Data[3]);}
                                                        if (CAN_Data[2] == 0x04) {EEPROM_Write(0x03,CAN_Data[3]);}
                                                        if (CAN_Data[2] == 0x05) {Algoritm_result = CAN_Data[3];}
                                                        Delay_ms(50);
                                                        Read_EEPROM();
                                                        counter_interrupt = 0;
                                                        INTCON.TMR0IE = 1;
                                                        }
                  BIE0.B0IE = 1;     //     Enable ECAN RX interrupt
                  PIE3.RXB0IE = 1;
                  } //if can_rcvd

if (CAN_Send_time == 0 && CAN_Send_flag == 1) {CAN_Send_flag = 0;
                                                            //CAN_Send_time = 0;
                                      CANWrite(P_ID, CAN_Data_Send, 8, Can_Send_Flags);}           // send initial messag



          } //while
}  // main
 //=============================================================================

     In fig. below you can see response in console from laser sensor. In strings shows result values of ADC function in microcontroller on photoresistor source.

   

No comments:

Post a Comment