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 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