'************************************************************************ 'EPILETTICO-CON-TASTIERA-FINALE.BAS '************************************************************************ 'AUTORE PK Lab- Cyber Solutions ' http://www.pklab.net - pk@pklab.net 'DATA gennaio 2002 ' 'Sw di gestione di un robot epilettico utilizzato come parte scenica 'nella tragedia endo-gonidia di Romeo Castellucci,Societas Raffaello Sanzio ' 'Durante il funzionamento il sw comunica via RSR-232 38400,N,8,1. 'E' possibile modificare alcuni parametri di funzionamento '************************************************************************ '****************** Direttive del compilatore ************************** ' '$regfile "89c51.dat" $regfile "reg51.dat" $romstart = &H0 ' indirizzo di partenza del codice ' frequenza di clock del micro per gli 8051 dei philips va raddoppiata ' perche' il chip ha un set istruzioni ridotto ma piu' veloce $crystal = 22118400 * 2 $baud = 19200 ' velocità di comunicazione RS-232 $large ' indirizzamento a 16 bit Config Sda = P3.4 ' specifico il pin dei DATI per I2CBUS Config Scl = P3.5 ' specifico il pin del CLK per I2CBUS '******************************************************************** ' Costanti scheda '******************************************************************** Const Io16w = &H040 ' Slave Addr. PCF8575 in WR Const Io16r = &H041 ' Slave Addr. PCF8575 in RD Const Pcf = &H090 ' Slave Address PCF8591 Const Ch0 = &H040 ' Canale 0 A/D Const Ch1 = &H041 ' Canale 1 A/D Const Ch2 = &H042 ' Canale 2 A/D Const Ch3 = &H043 ' Canale 3 A/D Const R = 1 ' operazione di lettura in I2CBUS Const W = 0 ' operazione di scrittura in I2CBUS Const Cler = 12 ' codice di clear screen Const Bel = 7 ' codice di Bell Const Cr = 13 ' codice di Enter Const Lf = 10 ' codice di line feed '******************************************************************** ' Costanti progetto '******************************************************************** Const Dentro = 255 Const Fuori = 0 Const Gambadx = 0 Const Gambasx = 1 Const Bracciodx = 2 Const Bracciosx = 3 Const Busto = 4 Const Numpistoni = 4 '4 arti piu busto al pistone 5 Const Rand = 100 Const Px = 60 'probabilita di commutare pistone 'Const Tc = 200 'Tempo di ciclo Const Toutmax = 2 'massimo tempo (Tc) per out pistone Const Tcbustomax = 3 'massimo tempo (Tc) per out pistone busto '******************************************************************** ' Variabili '******************************************************************** Dim Tout(numpistoni) As Byte 'num cicli di out per pistone i-esimo Dim Pistoni As Byte 'stato dei pistoni (1=out 0=in) Dim Tcbusto As Byte Dim Tc As Integer , Tcmezzi As Integer , Tx As Integer Dim Auto As Bit 'auto=1 => automatico auto=0 =>manuale Dim V8bit As Byte , Pulsanti As Byte Dim X As Word , I As Byte , J As Byte , K As Integer , T As Integer , Trun As Integer Dim X1 As Byte , Tw As Integer '( Dim Dac As Byte Dim Hind As Byte Dim Lind As Byte Dim Sa As Byte ' indirizzo dello Slave Address Dim Ind As Word ' indirizzo per I2CBUS ecc. a 16 Bit Dim Valore As Byte ' val. da scrivere,leggere I2CBUS ecc. Dim W_r As Byte ' sel. scrittura o lettura con R e WDim Hind As Byte ' byte Hight di Ind ') '******************************************************************** ' declare subroutine '******************************************************************** Declare Sub Init Declare Sub Uscite(v8bit As Byte) Declare Sub Att_key Declare Sub Visbyte (v8bit As Byte ) Declare Sub I2cbus (sa As Byte , Ind As Word , Valore As Byte , W_r As Byte) Declare Sub Outref Declare Sub Waitmillisec(tw As Integer) Declare Sub Versione0(t As Integer , Tx As Integer) Declare Sub Versione1(t As Integer , Tx As Integer) Declare Sub Versione2(t As Integer , Tx As Integer) '******************************************************************** '******************************************************************** ' M A I N '******************************************************************** '******************************************************************** Main: Waitms 2 ' ritardo per assestamento segnali Init ' Inizializzazioni della schedaCall Init 'POSSIBILI COMBINAZIONI DI PISTONI '1 2 3 4 '1 2 4 3 '1 3 2 4 '1 3 4 2 '1 4 3 2 '1 4 2 3 '2 1 3 4 '2 1 4 3 '2 3 4 1 '2 3 1 4 '2 4 3 1 '2 4 1 3 '3 1 4 2 '3 1 2 4 '3 2 1 4 '3 2 4 1 '3 4 1 2 '3 4 2 1 '4 1 2 3 '4 1 3 2 '4 2 3 1 '4 2 1 3 '4 3 1 2 '4 3 2 1 ' ottima vibrazione: Versione0 Tc = 20 Do Call Tinput If Pulsanti.7 = 0 Then 'selezione mod automatica Auto = 1 Call Versione0(3 , 20) Call Versione2(3 , 250) Else 'selez su manuale Auto = 0 Pistoni = Pulsanti Call Uscite(pistoni) End If Loop Do X = 10 Print "scegli la versione 0,1,2:" Input X Select Case X Case 0 : Call Versione0 Case 1 : Call Versione1 Case 2 : Call Versione2 End Select Loop End '********************************************************************** '*********************** Fine del programma *************************** ' ' '*************************** Procedure ******************************** ' '********************************* Init ******************************* Sub Init Pistoni = Dentro Tcbusto = 0 Call Uscite(pistoni) End Sub '********************* Pilota le uscite su CN4 ************************ 'La Gestione Di Queste Uscite Avviene Gestendo Il Port 1 Di Ic15 , 'Opportunamente Bufferati , I Quali Sono Stati Accuratamente Scelti , 'In Modo Da Semplificare Al Massimo La Gestione Software (per Maggiori 'Informazioni Vedere Il Capitolo descrizione Software Delle Periferiche Di 'Bordo). ' ' Procedura pilota le 8 uscite presenti su CN4, ' Parametri: ' Ingresso: v8bit as byte rappresenta lo stato delle uscite ' Uscita: nessuno '********************************************************************** ' Sub Uscite (v8bit As Byte) ' Pilota le uscite su CN4 I2cstart ' sequenza di Start per I2CBUS I2cwbyte Io16w ' comunico lo Slave address I2cwbyte &HFF ' gli 8 inp pongo alti I2cwbyte V8bit ' attivo gli 8 out I2cstop 'Call Visbyte(pistoni) 'Call Outref End Sub '****************** Attesa sospensiva di un tasto ********************* ' Attende l'arrivo di un carattere dalla seriale, e lo converte nel ' codice ASCII a 7 bit, se il carattere 'e minuscolo lo converte in ' maiuscolo. ' Parametri ' Ingresso: nessuno. ' Uscita: T as byte, carattere ricevuto '********************************************************************** ' '( Sub Att_key T = Inkey Do T = Inkey ' leggo la seriale Loop Until T <> 0 ' attendo arrivo di un carattere T = T And &H7F ' elimino il bit8 If T > 64 Then ' é una lettera T = T And &B01011111 ' converto in maiuscolo End If End Sub ') '********************* Visualizza un bite in bit ********************** ' Procedura che visualizza lo stato di ogni bit che compongono un byte ' indica con Off quando disattivo e On quendo attivo. ' Parametri: ' Ingresso: v8bit as byte valore da rappresentare come stato dei bit ' Uscita: nessuno '********************************************************************** Sub Visbyte (v8bit As Byte ) For X = 1 To 8 ' visualizzo per 8 volte il bit puntato X1 = V8bit And &H01 ' elimino tutti i bit tranne bit0 If X1 = 0 Then ' controllo lo stato del bit Print " On " ; ' se=0 visualizzo On Else Print " Off" ; ' se=1 visualizzo Off End If Shift V8bit , Right ' sposto a destra di 1 bit Next X Printbin 10 ; 13 End Sub '********************** fornisce in uscita un segnale analogico***************** ' Gestione A/D e D/A IC1 '( Sub Outref Dac = 0 For K = 0 To Numpistoni If Pistoni.k = Fuori Then Dac = Dac + 50 End If Next K If Pistoni.busto = Fuori Then Dac = Dac + 50 End If Call I2cbus(pcf , Ch0 , Dac , W) ' scrivo il valore in I2cBUS End Sub ') '****************** Letture e scrittura su EEPROM e RAM/RTC *********** ' Questa procedura scrive o legge attraverso I2cBUS su EEPROM e RAM/RTC ' nel campo che va da &H000 fino &H7FF, ' Parametri: ' Ingresso: Sa as byte contiene lo Slave Address del componente ' Ind as word contiene indirizzo del dispositivo, ' Valore as byte valore da scrivere o leggere ' W_R as bit se 0 scrivo, se = 1 leggo ' Uscita: Valore as byte contiene il dato letto '********************************************************************** '( Sub I2cbus (sa As Byte , Ind As Word , Valore As Byte , W_r As Byte) Hind = High(ind) ' prelevo il byte alto Lind = Low(ind) ' prelevo il byte basso Hind = Hind And 7 ' prelevo i 3 bit bassi Shift Hind , Left , 1 ' sposto a sinistra di 1 bit Hind = Hind Or Sa ' sommo lo slave address con scrittura If W_r = 0 Then ' controllo se devo leggere o scrivere I2cstart ' sequenza di start I2cwbyte Hind ' slave address I2cwbyte Lind ' asdress of EEPROM I2cwbyte Valore ' valore da scrivere I2cstop ' sequenza di stop Waitms 10 ' ritardo di 10ms necessario alla ' EEPROM dopo ogni scrittura Else Hind = Hind Or 1 I2cstart ' ripeto lo start I2cwbyte Hind ' slave address I2crbyte Valore , Nack ' leggo I2cstop ' sequenza di stop End If End Sub ') '*************************************************************************** 'Questa funzione e' necessaria perche la funzione waitms riceve un byte 'quindi un valore tra 0..255 ms. Sub Waitmillisec(tw As Integer) '*************************************************************************** If Tw > 255 Then K = Tw Mod 255 Waitms K K = Tw / 255 For J = 0 To K Waitms 255 Next J Else Waitms Tw End If End Sub '*************************************************************************** 'T = durata in secondi ' ATTENZIONE!! T viene convertito in ms dalla funzione ' quindi T < 65 sec alla volta perche' T è integer ' è valido il range 0..65536 ms cioe' 0..65s 'Tc = periodo di ciclo in millisecondi Sub Versione0(t As Integer , Tx As Integer) '*************************************************************************** T = T * 1000 'porto la durata in msec Tc = Tx Trun = 0 Print "(versione0) V per variare TC attuale:" Print Tc Do 'sceglie un pistone a caso se uso un parametro per rnd troppo piccolo ' esempio 4 i valori non sono casuali :( J = Rnd(100) Select Case J Case Is > 75 : J = 3 Case Is > 50 : J = 2 Case Is > 25 : J = 1 Case Is > 0 : J = 0 End Select For I = J To 3 Pistoni.i = Fuori Call Uscite(pistoni) Call Waitmillisec(tc) 'Waitms Tc Pistoni.i = Dentro Call Uscite(pistoni) Call Waitmillisec(tc) 'Waitms Tc Next I 'gestione separata movimenti del busto ' Il busto e' molto piu' pesante quindi ON/OFF piu' lenti 'Incr Tcbusto 'If Tcbusto > Tcbustomax Then ' Tcbusto = 0 Pistoni.busto = Not Pistoni.busto 'End If 'pressione tasto per modificare i parametri usa RS232 38400 N,8,1 X = Inkey If X = "v" Or X = "V" Then Input "Ins. nuovo valore: " , Tc Print "(versione 0)V per variare TC attuale:" Print Tc X = 0 End If Trun = Tc + Trun If Auto = 0 Then Exit Do End If Loop Until Trun > T End Sub '*************************************************************************** 'versione obsoleta NON utilizzata. Andrebbe modificata inserendo i 'parametri T e Tc Sub Versione1 '*************************************************************************** Tc = 200 Tcmezzi = Tc / 2 Print "V per variare TC attuale:" Print Tc Do 'sceglie un pistone a caso se uso un parametro per rnd troppo piccolo ' esempio 4 i valori non sono casuali :( J = Rnd(100) Select Case J Case Is > 75 : J = 3 Case Is > 50 : J = 2 Case Is > 25 : J = 1 Case Is > 0 : J = 0 End Select For I = J To 3 Pistoni.i = Fuori Call Uscite(pistoni) Call Waitmillisec(tc) 'Waitms Tc Pistoni.i = Dentro Call Uscite(pistoni) Call Waitmillisec(tcmezzi) 'Waitms Tc Next I 'gestione separata movimenti del busto 'Incr Tcbusto 'If Tcbusto > Tcbustomax Then ' Tcbusto = 0 Pistoni.busto = Not Pistoni.busto 'End If 'pressione tasto per modificare i parametri X = Inkey If X = "v" Or X = "V" Then Input "Ins. nuovo valore: " , Tc Tcmezzi = Tc / 2 Print "V per variare TC attuale:" Print Tc X = 0 End If Loop End Sub '************************************************************************ 'T = durata in secondi (massimo 60 sec alla volta) 'Tc = periodo di ciclo in millisecondi Sub Versione2(t As Integer , Tx As Integer) '************************************************************************ 'Tc = 200 T = T * 1000 'porto la durata in msec Tc = Tx Trun = 0 Tcmezzi = Tc / 2 Print "(versione 2)V per variare TC attuale:" Print Tc Do 'sceglie un pistone a caso se uso un parametro per rnd troppo piccolo ' esempio 4 i valori non sono casuali :( J = Rnd(100) Select Case J Case Is > 75 : J = 3 Case Is > 50 : J = 2 Case Is > 25 : J = 1 Case Is > 0 : J = 0 End Select I = J 'For I = J To 3 Pistoni.i = Fuori Call Uscite(pistoni) Call Waitmillisec(tc) 'Waitms Tc Pistoni.i = Dentro Call Uscite(pistoni) Call Waitmillisec(tcmezzi) 'Waitms Tc 'Next I 'gestione separata movimenti del busto ' Il busto e' molto piu' pesante quindi ON/OFF meno frequenti Incr Tcbusto If Tcbusto > Tcbustomax Then Tcbusto = 0 Pistoni.busto = Not Pistoni.busto Call Uscite(pistoni) End If 'pressione tasto per modificare i parametri X = Inkey If X = "v" Or X = "V" Then Input "Ins. nuovo valore: " , Tc Tcmezzi = Tc / 2 Print "(versione 2) V per variare TC attuale:" Print Tc X = 0 End If Trun = Tc + Trun If Auto = 0 Then Exit Do End If Loop Until Trun > T End Sub '********************* Gestione ingressi uscite *********************** ' I cablaggio degli ingressi digitali e' stato fatto in modo che ' Ad ogni pulsante un bit ' ad ogni bit corrisponde un pistone ' l'utimo bit controlla lo stato auto/manual ' ' Sub Tinput Tcon.0 = 1 ' Setto INT0 attivo sul fronte di discesa Enable Int0 ' Abilito l'interrupt INT0 Enable Interrupts ' abilito l'uso degli interrupt 'Pulsanti = P1 ' leggo CN2 'Call Visbyte(p1) ' visualizzo tutti gli 8 bit 'Print " "; I2creceive Io16r , Pulsanti ' leggo 8 bit su CN5 'Call Visbyte(pulsanti) ' visualizzo tutti gli 8 bit 'Print Chr(13); ' metto il cursore a capo della riga Waitms 5 ' ritardo di 255ms Disable Interrupts ' disabilito l'uso degli interrupt Disable Int0 ' disabilito l'interrupt INT0 End Sub '( '********************* Dichiarazione risposta su INT0 ***************** ' On Int0 Rtc_int0 ' dichiaro la procedura di risposta all'INT0 ' generato dall'RTC ' '********************* Risposta all'interrupt INT0 ******************** ' Rtc_int0: ' risposta all'interrupt INT0 Auto = 1 ' incremento la variabile ad ogni interrupt Return ')