' Interface de Poursuite- W4SM TrackSM - F1HDI/F1OAT/F5DJL - version 1.1 14/11/2006 ' Reception du flux Nova el/az a 4800 bps sur USART sous interruption ' La chaine recue de TrackSM est stockee dans le tableau "chaine_aff" ' Define CONF_WORD = 0x3f3a Define SEROUT_DELAYUS = 5000 ' ' Declarations variables communes au versions Dim i As Byte Dim j As Byte Dim k As Byte Dim l As Byte Dim m As Byte Dim temp(5) As Byte Dim compteur_boucle As Byte Dim diff As Word 'Calcul de difference ' Dim char_cnt As Byte 'Compteur de character ' Dim chaine_rs(40) As Byte 'Chaine d entree du flux Dim chaine_aff(40) As Byte 'Chaine de traitement quand trame recue Dim chaine_len As Byte 'Longeur de la trame recue ' Dim valeur_capteur_az As Word 'Valeur ADC 1 AZ brute sur 1024 Dim valeur_capteur_el As Word 'Valeur ADC 0 EL brute sur 1024 points Dim valeur_capteur_az_deg As Word Dim valeur_capteur_el_deg As Word Dim long_valeur_capteur_az_deg As Long Dim long_valeur_capteur_el_deg As Long Dim valeur_consigne_az As Word 'Valeur binaire az sans decimale de trame recue Dim valeur_consigne_el As Word 'Valeur binaire el sans decimale de trame recue Dim az_sup As Bit 'A 1 si consigne superieure a valeur Dim el_sup As Bit 'A 1 si consigne superieure a valeur Dim diff_az As Word Dim diff_el As Word Dim cali_az_min As Word Dim cali_az_max As Word Dim elevation_horizon_0 As Word Dim chaine_recue As Bit 'Flag de trame complete (0A recu) Dim rotor_tracking_az As Bit Dim rotor_tracking_el As Bit Dim delay_arret As Bit Dim az_enable As Bit Dim el_enable As Bit Dim sortie_cal As Bit Dim cali_flag As Byte Dim chaine_traitee As Byte 'extraction de az et elevation correcte du RS232 Dim cpt_point_el As Word Dim cpt_point_az As Word Dim hysteresis_el As Word 'Hysteresis elevation dans cette version 1/10 deg Dim hysteresis_az As Word 'Hysteresis azimut dans cette version 1/10 deg Dim consigne_el_max As Word ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Pbus section ' Symbol pbus_rts = RB1 Symbol pbus_data = RB2 Dim pbus_devid As Byte Dim pbus_cmd As Byte Dim pbus_len As Byte Dim pbus_msg(16) As Byte Dim pbus_checksum As Byte Dim elevation As Word Dim pbus_timeout As Bit ' ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Section version F5DJL Deltawave ' Symbol led_boucle = RB5 ' Symbol led_debug = RB4 ' Symbol haut = RB0 ' Symbol bas = RB1 ' Symbol gauche = RB2 ' Symbol droite = RB3 ' Const az_rotor_range = 3600 ' pour 1024 points ' Const el_rotor_range = 1800 ' pour 1024 points ' Const speed_cw = 150 ' duree du point cw led ' Const relay_on = 50 ' duree en ms min de cde on relais ' Const relay_off = 30 ' duree en ms de trainee du relais ' TRISB = 0x00 'set all PORTB pins as outputs ' Section version F1HDI Olimex Symbol led_boucle = RB4 Symbol led_debug = RB5 Symbol haut = RD4 Symbol bas = RD5 Symbol gauche = RD6 Symbol droite = RD7 Const az_rotor_range = 4500 ' pour 1024 points Const el_rotor_range = 900 ' pour 1024 points Const speed_cw = 150 ' duree du point cw led Const relay_on = 50 ' duree en ms min de cde on relais Const relay_off = 30 ' duree en ms de trainee du relais TRISB = 0x04 'set all PORTB pins as outputs, except RB2 for P-BUS ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Declarations des Ports TRISA = 0xff 'Port a en input TRISD = 0x00 'set all PORTD pins as outputs - utilise chez DJL pour pour rotor chez HDI PORTD = 0x00 'make all PORTD pins Low ' 'Initialisation port serie Hseropen 4800 WaitMs 250 ' 'Initialisation de AN0 et AN1 ' Define ADC_CLOCK = 2 '32 Tosc Define ADC_SAMPLEUS = 200 'Sampling time 200 microsec ADCON1 = 0x04 'configure AN0 et AN1 input for analog use ' Validation des interruptions sur character recue USART ' PIE1.RCIE = 1 'enable usart receive interrupt INTCON.PEIE = 1 'enable all un-masked peripheral interrupt INTCON.GIE = 1 'enable all un-masked interrupts ' ' Debut du programme ' main: ' Affichage pendant 1 s led au demarrage Call trait_cw() WaitMs 500 Call read_eeprom() Call led_k() Select Case cali_flag Case 1 valeur_consigne_az = 0 valeur_consigne_el = 0 consigne_el_max = 870 Case 2 valeur_consigne_az = 0 valeur_consigne_el = 0 Else valeur_consigne_az = 0 valeur_consigne_el = 0 cali_az_max = 1023 cali_az_min = 0 elevation_horizon_0 = 1780 consigne_el_max = 870 hysteresis_el = 15 'Hysteresis elevation dans cette version 1/10 deg hysteresis_az = 10 'Hysteresis azimut dans cette version 1/10 deg Call trait_cw() EndSelect WaitMs 1000 ' Initialisation des variables char_cnt = 0 chaine_recue = 0 chaine_traitee = 3 cpt_point_az = 0 cpt_point_el = 0 az_enable = 1 el_enable = 1 rotor_tracking_az = 0 rotor_tracking_el = 0 sortie_cal = 0 compteur_boucle = 1 delay_arret = 0 For i = 1 To 40 chaine_rs(i) = 0 chaine_aff(i) = 0 Next i Call arret_az() Call arret_el() 'Debut de la routine de boucle principale main_loop: ' Toggle led_boucle ' Visibilise l' activite boucle principale WaitMs 200 ' ''''''''''''''''''''''''''''''Routine traitement chaine ascii recue ''''''''''' If chaine_recue = 1 Then Call traitement_chaine() chaine_recue = 0 Endif ' ''''''''''''''''''''''''''''''Routine Traitement des park speciaux '''''''''''''' If chaine_traitee = 1 Then Select Case valeur_consigne_az Case 6390 ' parking active 999 (6390 transmis) Call calibration_az() sortie_cal = 1 Case 5100 ' parking active a 870 (5100 transmis) Call calibration_hor_el() sortie_cal = 1 Case 5200 ' parking active a 880 (5200 transmis) Call hysteresis_az() sortie_cal = 1 Case 5300 ' parking active a 890 (5300 transmis) Call hysteresis_el() sortie_cal = 1 Case 5000 ' parking active a 860 (5000 transmis) Call init_eeprom() sortie_cal = 1 EndSelect If sortie_cal = 1 Then rotor_tracking_az = 0 rotor_tracking_el = 0 chaine_traitee = 0 sortie_cal = 0 Endif Endif ' ''''''''''''''''''''''Routine pointage Elevation '''''''''''''''''''''''''''''''' ' If el_enable = 1 And rotor_tracking_el = 1 Then Call diff_elevation() If valeur_consigne_el < consigne_el_max Then If diff_el > hysteresis_el Then cpt_point_el = cpt_point_el + 1 ' Hserout "#pointage EL", #cpt_point_el, CrLf Endif While diff_el > hysteresis_el Select Case el_sup Case 0 Call descendre() WaitMs relay_on delay_arret = 1 Case 1 Call monter() WaitMs relay_on delay_arret = 1 EndSelect Call diff_elevation() Wend Endif 'sortie_el: If delay_arret = 1 Then WaitMs relay_off 'Motor trainée delay_arret = 0 Endif Call arret_el() rotor_tracking_el = 0 Endif ' '''''''''''''''''''' Pointage Azimut '''''''''''''''''''''''''''''''' If az_enable = 1 And rotor_tracking_az = 1 Then Call diff_azimut() While diff_az > hysteresis_az Select Case az_sup Case 0 Call tourner_gauche() WaitMs relay_on delay_arret = 1 Case 1 Call tourner_droite() WaitMs relay_on delay_arret = 1 EndSelect Call diff_azimut() Wend sortie_az: If delay_arret = 1 Then WaitMs relay_off 'Motor trainée delay_arret = 0 Endif Call arret_az() rotor_tracking_az = 0 Endif ' '''''''''''''''''''''Routine Affichage '''''''''''''''''''''''''''''''' If compteur_boucle = 1 Then Call diff_azimut() Call diff_elevation() Gosub affichage_rs232 'Affichage consignes et capteurs vers RS 232 compteur_boucle = 100 Else compteur_boucle = compteur_boucle - 1 Endif chaine_traitee = 3 Goto main_loop End ' ' Routine Affichage RS232 affichage_rs232: Hserout 27, 91, 50, 74, CrLf Hserout " J79DI- Moon Tracker version 1.1 - ", CrLf, CrLf Hserout " Capteur AZ: ", #valeur_capteur_az_deg, " EL: ", #valeur_capteur_el_deg, CrLf Hserout " Consigne AZ: ", #valeur_consigne_az, " EL: ", #valeur_consigne_el, CrLf Hserout " Difference AZ: ", #diff_az, " Difference El : ", #diff_el, CrLf, CrLf Hserout " Calibration Az_max : ", #cali_az_max, " Az_min : ", #cali_az_min, " Horizon cal :", #elevation_horizon_0, CrLf, Hserout " Hysteresis Az : ", #hysteresis_az, " Hysteresis El: ", #hysteresis_el, CrLf Hserout " Range El max :", #consigne_el_max, " Flag Calibration: ", #cali_flag, CrLf, CrLf Return ' Routine interruption sur character recu RS232 On Interrupt 'interrupt routine Save System 'sauvegarde contexte ' If char_cnt < 40 Then 'Protection contre flux > 40 characters char_cnt = char_cnt + 1 Else char_cnt = 0 Endif ' loop_rs: Hserget l 'Character valide dans chain_rs(char_cnt) If l > 0 Then chaine_rs(char_cnt) = l Toggle led_debug Else Goto loop_rs Endif ' If chaine_rs(char_cnt) = 10 Then ' Si LF recu alors transfer de la chaine dans chaine_aff chaine_len = char_cnt For m = 1 To chaine_len chaine_aff(m) = chaine_rs(m) Next m chaine_recue = 1 ' flag de chaine recue Low led_debug char_cnt = 0 ' RAZ compteur character Endif PIR1.RCIF = 0 'enable new usart interruption Resume Proc traitement_chaine() ' Routine de traitement de la chaine recue ' lit la chaine recue identifie A et E pour extraction de la ' valeur binaire de AZ :az et EL :el ainsi que la partie entiere ' dans valeur_consigne_az et valeur consigne_el ' traitement_chaine: ' chaine_traitee = 3 For i = 1 To chaine_len 'lit la chaine Select Case chaine_aff(i) Case 65 'si A trouvee calcul de az k = 1 j = i + 3 'initialise k et jump apres ":" chaine_traitee = chaine_traitee - 1 ' "A" de AZ identifie boucle_az: Select Case chaine_aff(j) Case 46 'si char = "." Goto decimale_az 'traitement decimale Case 32 'si " " fin de chaine Goto fin_az Case Else 'autre cas charge digit ascci dans temp(k) temp(k) = chaine_aff(j) j = j + 1 k = k + 1 'incremente pointeur temp EndSelect Goto boucle_az decimale_az: j = j + 1 'incremente lecture chaine (saut du point) Goto boucle_az fin_az: 'calcul de la valeur decimale 299.6 =2996 valeur_consigne_az = asc2bin(temp(1), temp(2), temp(3), temp(4), k) ' ' Case 69 'si E trouve clacul de el k = 1 j = i + 3 'initialise k et jump apres ":" chaine_traitee = chaine_traitee - 1 ' "E" de EL identifie boucle_el: Select Case chaine_aff(j) Case 46 'si char = "." Goto decimale_el 'traitement decimale Case 13, 32 'si cr ou " " fin de chaine Goto fin_el Case Else 'autre cas charge digit ascci dans temp(k) temp(k) = chaine_aff(j) j = j + 1 k = k + 1 'incremente pointeur temp EndSelect Goto boucle_el decimale_el: j = j + 1 'incremente lecture chaine (saut du point) Goto boucle_el fin_el: 'calcul de la valeur decimale 85.1 = 851 valeur_consigne_el = asc2bin(temp(1), temp(2), temp(3), temp(4), k) EndSelect Next i rotor_tracking_az = 1 rotor_tracking_el = 1 End Proc Proc diff_azimut() valeur_capteur_az = adc_read_filt(1) long_valeur_capteur_az_deg = (az_rotor_range * (valeur_capteur_az - cali_az_min)) / (cali_az_max - cali_az_min) valeur_capteur_az_deg = long_valeur_capteur_az_deg.LW If valeur_consigne_az > valeur_capteur_az_deg Then diff_az = valeur_consigne_az - valeur_capteur_az_deg az_sup = 1 Else diff_az = valeur_capteur_az_deg - valeur_consigne_az az_sup = 0 Endif End Proc Proc diff_elevation() Call request_pbus_elevation() Call read_pbus_elevation() ' Result in elevation and pbus_timeout WaitMs 200 If pbus_timeout = 0 Then valeur_capteur_el = elevation - elevation_horizon_0 long_valeur_capteur_el_deg = (el_rotor_range * valeur_capteur_el) / 1024 valeur_capteur_el_deg = long_valeur_capteur_el_deg.LW If valeur_consigne_el > valeur_capteur_el_deg Then diff_el = valeur_consigne_el - valeur_capteur_el_deg el_sup = 1 Else diff_el = valeur_capteur_el_deg - valeur_consigne_el el_sup = 0 Endif Endif End Proc ' Proc arret_az_el() 'arrêt des moteurs Call arret_az() Call arret_el() End Proc ' Proc arret_az() 'arrêt moteur d'azimut Low droite Low gauche End Proc ' Proc tourner_gauche() 'tourner à gauche Low droite High gauche End Proc ' Proc tourner_droite() 'tourner à droite Low gauche High droite End Proc ' Arrêt moteur de site Proc arret_el() Low bas Low haut End Proc ' Monter moteur de site Proc monter() Low bas High haut End Proc ' Descendre moteur de site Proc descendre() Low haut High bas End Proc ' ' Fonction de lecture de l ADC (parametre 0 ou 1) et moyenne sur 5 echantillons ' Function adc_read_filt(arg1 As Byte) As Word Dim v(5) As Word Dim vm As Word PIE1.RCIE = 0 ' disable interrupt RS232 For i = 0 To 4 ' Acquisition de 5 valeurs Adcin arg1, v(i) Next i vm = 0 For i = 0 To 4 ' Calcul moyenne des 5 lectures vm = vm + v(i) Next i vm = vm / 5 ' adc_read_filt = vm PIE1.RCIE = 1 ' enable interrupt RS232 End Function ' Routine Lecture dans l EEPROM Proc read_eeprom() Read 0, cali_flag Read 1, cali_az_max.HB Read 2, cali_az_max.LB Read 3, cali_az_min.HB Read 4, cali_az_min.LB Read 5, elevation_horizon_0.HB Read 6, elevation_horizon_0.LB Read 7, hysteresis_az.HB Read 8, hysteresis_az.LB Read 9, hysteresis_el.HB Read 10, hysteresis_el.LB End Proc 'Fonction de conversion ascii 5 characters max en binaire (max 9999 , arg 5 = nb de digit inclus decimale)) ' Function asc2bin(arg1 As Byte, arg2 As Byte, arg3 As Byte, arg4 As Byte, arg5 As Byte) As Word Select Case arg5 Case 3 arg1 = arg1 - 48 arg2 = arg2 - 48 asc2bin = (arg1 * 10) + arg2 Case 4 arg1 = arg1 - 48 arg2 = arg2 - 48 arg3 = arg3 - 48 asc2bin = ((arg1 * 100) + (arg2 * 10) + arg3) Case 5 arg1 = arg1 - 48 arg2 = arg2 - 48 arg3 = arg3 - 48 arg4 = arg4 - 48 asc2bin = ((arg1 * 1000) + (arg2 * 100) + (arg3 * 10) + arg4) EndSelect End Function ' 'Fonction valeur absolue d' un nombre signé sur un WORD ' Function abs(arg1 As Word) As Word If arg1 > 32768 Then abs = Not arg1 abs = abs + 1 Else abs = arg1 Endif End Function ' Routine clignotement k sur led_boucle Proc led_k() Call trait_cw() Call point_cw() Call trait_cw() Call space_cw() End Proc Proc trait_cw() Dim trait_cw As Word trait_cw = 3 * speed_cw High led_boucle WaitMs trait_cw Low led_boucle WaitMs speed_cw End Proc Proc point_cw() High led_boucle WaitMs speed_cw Low led_boucle WaitMs speed_cw End Proc Proc space_cw() Dim space_cw As Word space_cw = 3 * speed_cw WaitMs space_cw End Proc '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' Section routine Calibration invoques paz des valeurs particuliere ' des consignes azimut via une commande park ' 1/ Calibration horizontale : Park a l' azimut 999 ' 2/ Calibration de l'offset vertical (valeur absolue du capteur a el=0) : Park 510 ' 3/ Effacement de la memoire EEPROM addresse 0 pour utilisation des valeurs hardcodees ' Dans tous les cas attendre fin de procedure signalee paz "AZ K" "EL K" ou "EE K" sur ' LED et console et retour en attente de commande ( attention si le park est maintenue ' la procedure recommence !!! '' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Proc calibration_az() Dim min As Word Dim minp As Word Dim max As Word Dim maxp As Word Call arret_az() Call arret_el() minp = 1024 'max range min = adc_read_filt(1) If min > 0 Then Call tourner_gauche() While minp > min minp = min WaitMs 1000 min = adc_read_filt(1) Wend Endif Call arret_az() cali_az_min = min maxp = 0 'min range max = adc_read_filt(1) If max < 1024 Then Call tourner_droite() While max > maxp maxp = max WaitMs 1000 max = adc_read_filt(1) Wend Endif Call arret_az() cali_az_max = max Call arret_el() ' 'routine ecriture dans l EEPROM Write 0, 1 Write 1, cali_az_max.HB Write 2, cali_az_max.LB Write 3, cali_az_min.HB Write 4, cali_az_min.LB WaitMs 250 Call led_k() WaitMs 1000 Call read_eeprom() Call led_k() End Proc Proc calibration_hor_el() Call request_pbus_elevation() Call read_pbus_elevation() ' Result dans elevation and pbus_timeout If pbus_timeout = 0 Then elevation_horizon_0 = elevation + 10 Write 0, 2 Write 5, elevation_horizon_0.HB Write 6, elevation_horizon_0.LB Endif ' Call led_k() Call read_eeprom() Hserout " Calibration Elevation terminee ", CrLf Hserout " valeur du capteur a el=0 ", #elevation, CrLf, CrLf WaitMs 1000 End Proc Proc hysteresis_az() hysteresis_az = valeur_consigne_el ' Routine ecriture dans l EEPROM Write 7, hysteresis_az.HB Write 8, hysteresis_az.LB Call led_k() Call read_eeprom() Hserout " Hysteresis az :", #hysteresis_az, CrLf, CrLf WaitMs 1000 End Proc Proc hysteresis_el() hysteresis_el = valeur_consigne_el ' Routine ecriture dans l EEPROM Write 9, hysteresis_el.HB Write 10, hysteresis_el.LB Call led_k() Call read_eeprom() Hserout " Hysteresis el :", #hysteresis_el, CrLf, CrLf WaitMs 1000 End Proc ' Routine Initialisation eeprom Proc init_eeprom() cali_flag = 1 cali_az_max = 1023 cali_az_min = 0 elevation_horizon_0 = 1780 hysteresis_el = 15 'Hysteresis elevation dans cette version 1/10 deg hysteresis_az = 10 'Hysteresis azimut dans cette version 1/10 deg Write 0, cali_flag Write 1, cali_az_max.HB Write 2, cali_az_max.LB Write 3, cali_az_min.HB Write 4, cali_az_min.LB Write 5, elevation_horizon_0.HB Write 6, elevation_horizon_0.LB Write 7, hysteresis_az.HB Write 8, hysteresis_az.LB Write 9, hysteresis_el.HB Write 10, hysteresis_el.LB WaitMs 100 Call read_eeprom() WaitMs 1000 End Proc '''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' ' Routines P-Bus F1OAT Novembre 2006 ' ' ''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Lecture de l elevation et mise dans elevation (WORD) Function read_pbus_elevation() As Byte ' Wait for RECHO answer Call recv_pbus_msg() elevation.HB = pbus_msg(0) 'Unit is 1/16 deg elevation.LB = pbus_msg(1) End Function ' Demande de l elevation pbus Proc request_pbus_elevation() ' Send CPING command High pbus_rts ' put ADM483 in tx ' send cping frame To device #1 Low pbus_data WaitMs 2 '5 Test SeroutInv pbus_data, 2400, 0x10, 0x5f, 0x91 WaitMs 2 '5 Test High TRISB.2 ' put back RB2 to input before ADM483 RX Low pbus_rts ' Put ADM483 in RX End Proc ' Lecture avec timeout de in pbus Function serin_timeout(serin_cpt As Word) As Byte While serin_cpt > 0 If pbus_data Then SerinInv pbus_data, 2400, serin_timeout Exit Endif serin_cpt = serin_cpt - 1 Wend pbus_timeout = 1 serin_timeout = 0 End Function ' Reception P-Bus message Proc recv_pbus_msg() Dim devid_len As Byte pbus_timeout = 0 wait_pbus: 'Serin pbus_data, 2400, devid_len, pbus_cmd ' wait For P-bus packet header devid_len = serin_timeout(50000) pbus_cmd = serin_timeout(1000) pbus_checksum = devid_len + pbus_cmd pbus_len = devid_len And 0x0f pbus_devid = devid_len / 16 For i = 0 To pbus_len pbus_msg(i) = serin_timeout(1000) pbus_checksum = pbus_checksum + pbus_msg(i) Next i If pbus_checksum <> 0 And pbus_timeout = 0 Then Goto wait_pbus ' corrupted packet End Proc