' **************************************************************** ' * File: gmbad.pbas - Ver. 1.1 * ' * Compilatore: mikroBasic for PIC by mikroElektronica * ' * IDE: mikroBasic for PIC by mikroElektronica * ' * Versione Compilatore: 1.1.6.0 * ' * Schede: 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 01.03.05 * ' **************************************************************** ' ' Questo demo offre due operativita' per la linea di ingresso analogico su CN7: ' calibrazione o acquisizione. ' La prima calcola un coefficiente di calibrazione grazie ad un segnale di ' riferimento esterno fornito dall'utente, e lo salva nella EEPROM interna del ' Mini Modulo. ' La seconda preleva il coefficiente di calibrazione dalla EEPROM, acquisice e ' rappresenta di continuo sulla console la combinazione dell'ingresso analogico, ' sia calibrato che non calibrato. Il demo puo' essere usato indifferentemente ' con range 0..2,5 V e 0..10 V. ' ' Rel 1.1 - by Graziano Gaiba ' Demo per effettuare conversioni A/D calibrate usando una GMB HR168 ' pilotata da un Mini Modulo GMM 4620 ' ' ' ***************** Definizioni del compilatore ****************** ' program gmbad ' ' *************** Dichiarazione delle costanti ******************* ' const ASC_c = 99 const ASC_cU = 67 ' ' ******************* Dichiarazione delle Variabili ******************** ' ' Variabili di uso generico dim d_in_l as byte dim d_in_h as byte dim ad_result as word ' ' ' Usate per la calibrazione dell'A/D converter dim Quant_err as word dim Vref_mV as word dim Vref_cmb as word dim sum_cmb as word dim KCal as word ' ' ' ******************* Definizione delle procedure ********************* ' ' ' Inizializzazione direzione segnali della CPU sub procedure Init_cpu ' ADCON1=$0f ' Imposta come I/O digitale i pin AN0..12 CMCON=$07 ' Imposta come I/O digitale RA0..4 ' Gli ingressi optoisolati di CN1 sono: ' 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 ' Gli ingressi optoisolati di CN2 sono: ' 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 ' Le uscite relays di CN3 sono: ' OUT A1 <-> RB4 ' OUT A2 <-> RB5 ' OUT B1 <-> RB6 ' OUT B2 <-> RB7 ' OUT C1 <-> RB3 ' OUT C2 <-> RB2 trisb=trisb and $03 ' Le uscite relays di CN4 sono: ' OUT D1 <-> RA3 ' OUT D2 <-> RC2 (J10 in posizione 3-4) trisa.3=0 trisc.2=0 ' Inizialzza modulo USART (8 bit, 19200 baud rate, ' no parity) Usart_init(19200) end sub ' ' ' Invia una stringa di caratteri alla porta seriale sub procedure print_USART(dim byref txt as char[255]) dim i as byte dim l as byte l = txt[0] for i = 1 to l USART_Write(txt[i]) next i end sub ' ' ' Invia CR + LF sub procedure print_CRLF USART_Write(10) USART_Write(13) end sub ' ' ' Pulisce lo schermo, inviando 25 volte CR + LF. sub procedure clrscr dim i as byte for i = 0 to 24 print_CRLF next i end sub ' ' ' Chiede la pressione di un tasto sub procedure wait_key dim c as byte print_usart("Premere un tasto...") do nop loop until USART_Data_Ready = 1 c = USART_Read end sub ' ' ' Procedura per impostare lo stato dei relays sui connettori CN3 e CN4. ' A seconda del valore dei bits di port_val, ogni relay viene attivato ' (contatto chiuso) o disattivato (contatto aperto). ' I bit di port_val hanno il seguente significato: ' -- CN3 ' port_val.0 pilota il relay OUT A1 ' port_val.1 pilota il relay OUT A2 ' port_val.2 pilota il relay OUT B1 ' port_val.3 pilota il relay OUT B2 ' port_val.4 pilota il relay OUT C1 ' port_val.5 pilota il relay OUT C2 ' -- CN4 ' port_val.6 pilota il relay OUT D1 ' port_val.7 pilota il relay OUT D2 ' ' Ogni bit ha il seguente significato: ' bit Significato ' 0 Relay disattivato (contatto aperto) ' 1 Relay attivato (contatto chiuso) sub procedure set_relays(dim port_val as byte) ' I relays sono pilotati in logica complementata , quindi anche port_val ' deve essere complementato port_val=port_val xor $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 end sub ' ' ' Inserimento di un valore decimale fino a cinque cifre. ' Il parametro in ingresso e' il numero di cifre, restituisce una ' word contenente il valore immesso. ' Gestisce il backspace (ASCII 08) ed accetta cifre in input ' da '0' a '9'. ' Iniva un carattere di bell (ASCII 07) quando riceve un dato ' non accettabile per l'input, o si tenta un inserimento o una ' cancellazione fuori dal range ammesso. sub function inputDEC(dim n_char as byte) as word dim str_input as byte[6] dim idx as byte dim chr_input as byte dim pow_of_10 as word[6] dim value as word pow_of_10[1] = 1 pow_of_10[2] = 10 pow_of_10[3] = 100 pow_of_10[4] = 1000 pow_of_10[5] = 10000 ' Indice deve partire da 1 idx = 1 Inc(n_char) ' Nessun carattere in input chr_input = 0 ' Valore iniziale value = 0 ' Continua finche' non riceve un carattere CR while chr_input <> 13 ' Se un dato e' pronto if usart_data_ready = 1 then ' Leggilo chr_input = USART_Read ' Se e' backspace (ASCII BS) if chr_input = 8 then ' e il buffer non e' vuoto if idx > 1 then ' Invia dato letto USART_Write(chr_input) ' Cancella carattere USART_Write(32) USART_Write(chr_input) ' Elimina ultimo dato letto Dec(idx) else ' Carattere bell per indicare un errore USART_Write(7) end if end if ' Se CR ricevuto, elabora il valore e restituiscilo if chr_input = 13 then n_char = 0 while idx > 1 Dec(idx) Inc(n_char) value = value + (str_input[n_char] - 48) * pow_of_10[idx] wend else ' Se il carattere puo' essere inserito if idx < n_char then ' Se il dato ricevuto e' valido: ' 0..9 if (chr_input >= 48) or(chr_input <= 57) then ' Invia il dato letto USART_Write(chr_input) ' Memorizzalo nel buffer di ingresso str_input[idx] = chr_input ' Punta alla posizione successiva Inc(idx) end if else ' Carattere bell per indicare un errore USART_Write(7) end if end if end if wend print_CRLF Result = value end sub ' ' ' Invia i suoi argomenti alla porta seriale come due cifre esadecimali. sub procedure print_HEX_2(dim value as byte) dim tmp as byte ' Nibble piu' significativo tmp = value >> 4 ' Se maggiore di 9, trasformalo in un carattere a partire da 'A' if tmp > 9 then tmp = tmp + 55 else ' Trasformalo in un carattere a partire da '0' tmp = tmp + 48 end if USART_Write(tmp) ' ' Nibble meno significativo tmp = value and $0f ' Se maggiore di 9, trasformalo in un carattere a partire da 'A' if tmp > 9 then tmp = tmp + 55 else ' Trasformalo in un carattere a partire da '0' tmp = tmp + 48 end if USART_Write(tmp) end sub ' ' ' Conversione di un canale A/D memorizzato nella variabile ad_canale. ' Il risultato e' una word che viene restituita. ' Prima di chiamare questa procedura, la periferica A/D converter ' deve essere configurata ed abilitata. sub function AD_Conversione(dim ad_canale as byte) as word dim ad_result as word adcon0.2 = ad_canale.0 adcon0.3 = ad_canale.1 adcon0.4 = ad_canale.2 adcon0.5 = ad_canale.3 adcon0.1 = 1 do nop loop until adcon0.1 = 0 ad_result = word(adresh << 8) + word(adresl) Result = ad_result end sub ' '********************** Programma principale *************************** ' main: Init_cpu ' Spegne i relays set_relays(0) for_ever: clrscr print_USART("Demo ingresso analogico Rel 1.1 for GMM 4620 rel 120304 e GMB HR168 rel 110104") print_CRLF print_CRLF print_USART("L'ingresso analogico e' il pin 8 di CN7.") print_CRLF print_USART("A seconda di J11 il range di input puo' essere da 0 a 5 V o da 0 a 20 V.") print_CRLF print_USART("La sezione analogic di GMB HR168 e` basata su componenti di precisione") print_CRLF print_USART("comunque soggetti a piccole tolleranze.") print_CRLF print_USART("Per compensarle e` preferibile acquisire l'ingresso analogico tramite") print_CRLF print_USART("calibrazione software.") print_CRLF print_USART("Il coefficiente di calibrazione viene memorizzato nelle ultime 8 locazioni") print_CRLF print_USART("della EEPROM interna della CPU, che sono riservate.") print_CRLF print_CRLF print_USART("Selezione modo: Acquisizione o Calibrazione (a/c): ") do nop loop until USART_Data_Ready = 1 d_in_h = USART_Read print_CRLF adcon1 = 0 adcon2 = $88 ' Abilita A/D converter adcon0.0 = 1 if (d_in_h = ASC_c) or (d_in_h = ASC_cU) then print_USART("Collegare J11 in 2-3.") print_CRLF print_USART("Collegare segnale di riferimento vicino al fondo scala (20 V) a pin 8 di CN7.") print_CRLF Vref_input: print_USART("Inserire il valore del segnale di riferimento, in mV (19000-20000): ") vref_mv = inputDEC(5) if vref_mv < 16000 then print_USART("Il segnale di riferimento deve essere superiore a 16000 mV.") print_CRLF goto Vref_input end if ' Procedura di calibrazione. ' Primo: calcolare la combinazione del segnale di riferimento. if vref_mv > 5000 then vref_cmb = (vref_mv * 1023) / 20000 else vref_cmb = (vref_mv * 1023) / 5000 end if ' Secondo: effettuare 64 misure del segnale di riferimento e calcolarne ' la media. sum_cmb = 0 for d_in_h = 0 to 64 ad_result = ad_conversione(4) sum_cmb = sum_cmb + ad_result next d_in_h ' Ultimo: calcolare il coefficiente di calibrazione usando la media ' delle 64 misure e la combinazione teorica del segnale di riferimento sum_cmb = sum_cmb >> 6 kcal = vref_cmb - sum_cmb ' Memorizza il coefficiente di calibrazione nelle locazione 03f8H e ' 03f9H della EEPROM interna. EEPROM_write($3f8, hi(kcal)) EEPROM_write($3f9, lo(kcal)) print_USART("Calibrazione completata.") print_CRLF print_CRLF end if ' ' Acquisizione ' Lettura del coefficiente di calibrazione dalla EEPROM interna. d_in_h = EEPROM_read($3f8) d_in_l = EEPROM_read($3f9) kcal = word(d_in_h << 8) + word(d_in_l) quant_err = 1023 / kcal print_USART("Combinazione NON calibrata e calibrata vengono mostrate continuamente.") print_CRLF print_USART("Premere un tasto per uscire...") print_CRLF print_CRLF print_USART("NON calibrata Calibrata") print_CRLF ' Ciclo visualizzazione do ad_result = ad_conversione(4) print_USART(" ") print_HEX_2(hi(ad_result)) print_HEX_2(lo(ad_result)) ad_result = ad_result - (ad_result / quant_err) print_USART(" ") print_HEX_2(hi(ad_result)) print_HEX_2(lo(ad_result)) USART_Write(13) delay_ms(200) loop until USART_Data_Ready = 1 d_in_h = USART_Read goto for_ever end.