' **************************************************************** ' * File: gmbade.bas - Ver. 1.1 * ' * Compiler: PIC Basic PRO * ' * IDE: MicroCode Studio Plus * ' * Compiler Version: 2.45 * ' * Boards: GMM 4620 + GMB HR168 * ' * GRIFO(R) via Dell'Artigiano 8/6 * ' * 40016 S. Giorgio di Piano (BO) * ' * Tel. +39 051 892052 Fax. +39 051 893661 * ' * http://www.grifo.com http://www.grifo.it * ' * by Graziano Gaiba 04.02.05 * ' **************************************************************** ' ' This demo offers two possibilities: calibration or acquisition. ' First action determinates a calibration coefficent using an ' external reference voltage provided by the user and stored it ' in Mini Module internal EEPROM. ' Second action fetches calibration coefficent from EEPROM, ' acquires and shows continuously on console the analog input ' combination, both uncalibrated and calibrated. ' Demo can be used without problems with range 0..5 V and 0..20 V. ' ' Rel 1.1 - by Graziano Gaiba ' Demo program of calibrated A/D conversion with GMB HR168 driven ' by Mini Module GMM 4620 ' ' ' ******************** Compiler definitions ********************** ' DEFINE OSC 10 ' Oscillator frequency 9,8304 MHz DEFINE HSER_RCSTA 90h ' Enable EUSART serial receiver DEFINE HSER_TXSTA 20h ' Enable EUSART serial transmitter DEFINE HSER_BAUD 19200 ' Baud Rate ' ' ******************* Constants declaration ********************** ' RTCSLA con $A0 I2C_BUFFER_SIZE con 10 ' ' ******************** Variables declaration ********************* ' ' Generic variables i var byte scelta var byte di var byte do var byte ' ' ' Used for calibration of A/D converter Quant_err var word Vref_mV var word Vref_cmb var word sum_cmb var word KCal var word ' ' Used by I/O management procedures port_val var byte ' Value read or to be written to the I/O ' ' Used by A/D converter management ad_channel var byte ad_result var word ' ' '************************** Main Program ******************************* ' main: gosub Init_cpu ' Turn OFF relays port_val = 0 gosub set_relays for_ever: gosub clrscr hserout ["Analog input demo Rel 1.1 for GMM 4620 rel 120304 and GMB HR168 rel 110104", 13, 10, 13, 10] hserout ["Analog input pin is pin 8 of CN7.", 13, 10] hserout ["According to J11 input range can be 0 to 5 V or 0 to 20 V", 13, 10] hserout ["Analog input section of GMB HR168 is based on precision components anyway", 13, 10] hserout ["subject to small tollerances.", 13, 10] hserout ["To compensate such tollerances it is suggersted to acquire analog input", 13, 10] hserout ["through a software calibration.", 13, 10] hserout ["Calibration coefficent is stored in the last 8 locations of CPU internal", 13, 10] hserout ["EEPROM, which are reserved.", 13, 10, 13, 10] hserout ["Select mode: Acquisition or Calibration (a/c): "] hserin [i] hserout [i, 13, 10] adcon1 = 0 adcon2 = $88 ' Enable A/D converter adcon0.0 = 1 if i == "c" or i == "C" then hserout ["Connect J11 in 2-3.", 13, 10] hserout ["Connect analog reference signal close to full scale (20 V) to pin 8 of CN7.", 13, 10] Vref_input: hserout ["Input the value of reference signal, in mV (19000-20000): "] hserin [dec5 vref_mv] hserout [dec5 vref_mv, 13, 10] if vref_mv < 16000 then hserout ["Vref must be more than 16000 mV for proper calibration.", 13, 10] goto Vref_input endif ' Calibration procedure ' First: calculate combination of reference voltage ' Please refer to Pic Basic Pro manual for more information ' about how a chain 16bit x 16bit multilply and DIV32 instruction work ' Here KCal acts as a dummy variable. kcal = vref_mv * 1023 if vref_mv > 5000 then vref_cmb = div32 20000 else vref_cmb = div32 5000 endif ' Second: make 64 measures of the voltage connected and obtain ' an average value sum_cmb = 0 for i = 0 to 64 ad_channel = 4 gosub ad_conversion sum_cmb = sum_cmb + ad_result next i ' Last: calculate a calibration coefficent using the average of the 64 ' measurements and the combination of reference voltage sum_cmb = sum_cmb >> 6 kcal = vref_cmb - sum_cmb ' Store the calibration coefficent in locations 03f8H and 03f9H ' of internal EEPROM write kcal.highbyte, $3f8 write kcal.lowbyte, $3f9 hserout ["Calibration completed.", 13, 10, 13, 10] endif ' ' Acquisition ' Read calibration coefficent from internal EEPROM read $3f8, kcal.highbyte read $3f9, kcal.lowbyte quant_err = 1023 / kcal hserout ["Uncalibrated and calibrated combinations are continuously visualized.", 13 ,10] hserout ["Press a key to exit...", 13, 10, 13, 10] hserout ["Not calibrated Calibrated", 13, 10] ' Visualization loop vis_loop: ad_channel = 4 gosub ad_conversion hserout [" ", hex4 ad_result] ad_result = ad_result - (ad_result / quant_err) hserout [" ", hex4 ad_result, 13] hserin 200, vis_loop, [i] goto for_ever end ' ' **************** Procedures definition ****************** ' ' ' CPU and signals directions initialization Init_cpu: ADCON1=$0f ' Imposta come I/O digitale i pin AN0..12 CMCON=$07 ' Imposta come I/O digitale RA0..4 ' Optocoupled Inputs of CN1 are: ' IN1-1 <-> RA0 ' IN2-1 <-> RA1 ' IN3-1 <-> RB0 ' IN4-1 <-> RB1 ' IN5-1 <-> RA4 ' IN6-1 <-> RC0 ' IN7-1 <-> RC1 ' IN8-1 <-> RC5 trisa.0 = 1 trisa.1 = 1 trisa.4 = 1 trisb.0 = 1 trisb.1 = 1 trisc.0 = 1 trisc.1 = 1 trisc.5 = 1 ' Optocoupled Inputs of CN2 are: ' IN1-2 <-> RD0 ' IN2-2 <-> RD1 ' IN3-2 <-> RD2 ' IN4-2 <-> RD3 ' IN5-2 <-> RD4 ' IN6-2 <-> RD5 ' IN7-2 <-> RD6 ' IN8-2 <-> RD7 trisd = $ff ' Relay outputs of CN3 are: ' OUT A1 <-> RB4 ' OUT A2 <-> RB5 ' OUT B1 <-> RB6 ' OUT B2 <-> RB7 ' OUT C1 <-> RB3 ' OUT C2 <-> RB2 trisb = trisb & $03 ' Relay outputs of CN4 are: ' OUT D1 <-> RA3 ' OUT D2 <-> RC2 (J10 in position 3-4) trisa.3 = 0 trisc.2 = 0 return ' ' ' Clear screen, sending 25 times CR + LF. clrscr: for i= 0 to 24 hserout [13, 10] next i return ' ' ' Asks for a key press wait_key: hserout ["Press a key..."] wait_key_loop: hserin 1, wait_key_loop, [i] return ' ' Conversion of A/D channel stored in variable ad_channel. ' Result in variable ad_result. ' Before calling this procedure, A/D converter peripheral must be ' configured and enabled. AD_Conversion: adcon0.2 = ad_channel.0 adcon0.3 = ad_channel.1 adcon0.4 = ad_channel.2 adcon0.5 = ad_channel.3 adcon0.1 = 1 ad_polling: if adcon0.1 = 1 then ad_polling ad_result.lowbyte = adresl ad_result.highbyte = adresh return ' ' ' Procedure to set the status of the relays on connectors CN3 and CN4. ' According to the bits of port_val, each relay is turned ON ' (contact closed) or OFF (contact open). ' Bits of port_val have this meanging: ' -- CN3 ' port_val.0 drives relay OUT A1 ' port_val.1 drives relay OUT A2 ' port_val.2 drives relay OUT B1 ' port_val.3 drives relay OUT B2 ' port_val.4 drives relay OUT C1 ' port_val.5 drives relay OUT C2 ' -- CN4 ' port_val.6 drives relay OUT D1 ' port_val.7 drives relay OUT D2 ' ' Each bit has the following meaning: ' bit Meaning ' 0 Relay turned OFF (contact open) ' 1 Relay turned ON (contact closed) set_relays: ' Relays are driven in complemented logic, so port_val must be ' complemented too port_val = port_val ^ $ff portb.4 = port_val.0 portb.5 = port_val.1 portb.6 = port_val.2 portb.7 = port_val.3 portb.3 = port_val.4 portb.2 = port_val.5 porta.3 = port_val.6 portc.2 = port_val.7 return