Forum: Mikrocontroller und Digitale Elektronik Analoge Datenerfassung mit einem PIC und PICBASIC


von Georg G. (Firma: ADV-Service) (mcgeorge)


Lesenswert?

Hallo NG, ich brauch bitte Eure Hilfe. Ich verstehe es nicht und hoffe, 
dass hier jemand ist, der mir sagen kann, was ich falsch mache.

Ich wollte eine möglichst einfache Lösung haben, um einen 1 Volt 
Analogwert von einer Meßsonde (Feuchtefühler) an meinen Mikrocontroller 
zu übertragen. Da ich schon andere Erweiterungen mit I2C angebunden 
habe, wollte ich einen Wandler haben 1 Volt analog => 12C.
Also habe ich mich für den PIC 16F1827 (18pin DIP) entschieden. Ich 
möchte die Spannungsversorgung des PICs über den I2C-Bus machen und den 
internen Oszillator des PICs nutzen, so das es eine "1-Chip-Schaltung" 
werden soll. Als Referenzspannung möchte ich die interne Quelle mit 
1,024 Volt verwenden.
Und da ich mich in Assembler nicht sooo gut auskenne habe ich mir 
PICBASIC gekauft.

Der Programmteil, der aus dem PIC ein I2C-Slave macht klappt. Abfrage, 
Antwort alles super. Was nicht klappt, ist die Abfrage des analogen 
Ports. Ich simuliere auf dem Port RA0 eine Spannung zwischen 0 und 1 V. 
Wenn ich den Wert über I2C abfrage, erhalte ich bis 0,5 Volt die Antwort 
1, zwichen 0,5 und 0,7 Volt eine 2 und ab 0,7 Volt eine 3. Mehr nicht?

Wo mache ich den Fehler?


Hier mein Code:
1
'****************************************************************
2
#CONFIG
3
  __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _MCLRE_OFF & _FCMEN_OFF
4
  __CONFIG _CONFIG2, _PLLEN_ON & _WRT_OFF & _STVREN_OFF & _BOREN_OFF
5
#ENDCONFIG
6
7
DEFINE OSC 16
8
OSCCON = %01111010
9
10
' Alias I2C pins
11
scl VAR PORTB.4        ' I2C clock input
12
sda VAR PORTB.1        ' I2C data input
13
14
' Define used register flags
15
SSPIF VAR PIR1.3       ' SSP (I2C) interrupt flag
16
BF    VAR SSPSTAT.0    ' SSP (I2C) Buffer Full
17
R_W   VAR SSPSTAT.2    ' SSP (I2C) Read/Write
18
D_A   VAR SSPSTAT.5    ' SSP (I2C) Data/Address
19
20
CKP   VAR SSPCON1.4     ' SSP (I2C) SCK Release Control
21
SSPEN VAR SSPCON1.5     ' SSP (I2C) Enable
22
SSPOV VAR SSPCON1.6     ' SSP (I2C) Receive Overflow Indicator
23
WCOL  VAR SSPCON1.7     ' SSP (I2C) Write Collision Detect
24
25
' Define constants
26
I2Caddress CON  2      ' Make our address 2
27
28
' Allocate RAM
29
result  VAR BYTE       ' ADC result
30
datain  VAR BYTE       ' Data in 
31
dataout VAR BYTE[8]    ' Data out array
32
readcnt VAR BYTE       ' I2C read count
33
34
'-----------------------------------------------------------------------
35
   
36
DEFINE ADC_BITS 10
37
DEFINE ADC_SAMPLEUS 50
38
'DEFINE ADC_CLOCK 3
39
40
ADCON0  = %00000001
41
ADCON1  = %01100011
42
TRISA.0 = 1
43
'TRISA   = %00000001
44
FVRCON  = %11000001
45
ANSELA  = %00000001
46
47
48
' Initialize I2C slave mode
49
   SSPADD = I2Caddress ' Set our address (Bit 7-1 = Adress, 0 = unused)
50
   SSPCON2 = 0         ' General call address disabled
51
   SSPCON1 = $36       ' Set to I2C slave with 7-bit address
52
                       ' 0011 0110 = 0x36
53
54
   readcnt = 0         ' Zero counter
55
56
   dataout[0] = "A"    ' Preset output data to "ADC=    "
57
   dataout[1] = "D"
58
   dataout[2] = "C"
59
   dataout[3] = "="
60
   dataout[4] = "0"
61
   dataout[5] = "0"
62
   dataout[6] = "0"
63
   dataout[7] = "0"
64
65
   GoTo mainloop       ' Skip over subroutines
66
67
68
' SSPBUF = SSP1BUF = ein Empfangs- und Sendebuffer (1 Byte/8 Bit)
69
70
'-----------------------------------------------------------------------
71
i2cslave:            ' I2C slave subroutine
72
'-----------------------------------------------------------------------
73
   SSPIF = 0         ' Clear interrupt flag PIR1.3
74
                     'SSPIF: Master Synchronous Serial Port Interrupt Flag bit
75
                     ' 1 = The transmission/reception is complete
76
                     ' 0 = Waiting to transmit/receive
77
                     
78
   IF ( R_W = 1 ) Then i2crd                ' Read data from us
79
   IF ( BF = 0 ) Then i2cexit               ' Nothing in buffer so exit
80
   IF ( D_A = 1 ) Then i2cwr                ' Data for us (not address)
81
   IF ( SSPBUF != I2Caddress ) Then i2cexit ' Clear the address from the buffer
82
   readcnt = 0                              ' Mark as first read
83
   Return
84
85
86
'-----------------------------------------------------------------------
87
i2cwr:                 ' I2C write data to us
88
'-----------------------------------------------------------------------
89
   datain = SSPBUF     ' Put data into array
90
   Return
91
92
93
'-----------------------------------------------------------------------
94
i2crd:                 ' I2C read data from us
95
'-----------------------------------------------------------------------
96
   IF ( D_A = 0 ) Then
97
      readcnt = 0      ' Mark as first read
98
   EndIF
99
100
   SSPBUF = dataout[readcnt]    ' Get data from array
101
   CKP = 1                      ' Release SCL line
102
   readcnt = readcnt + 1        ' Move along read count
103
   Return
104
105
106
'-----------------------------------------------------------------------
107
mainloop:              ' Main program loop
108
'-----------------------------------------------------------------------
109
110
   IF ( SSPIF = 1 ) Then       ' Check for I2C interrupt flag
111
      GoSub i2cslave
112
   EndIF
113
114
   ADCIN 0, result     ' Read ADC channel 0
115
   
116
   dataout[4] = result
117
118
   GoTo mainloop       ' Do it all forever
119
   End
120
121
'-----------------------------------------------------------------------

Bitte nicht meckern, ich bin auf dem Gebiet der Prozessorprogrammierung 
totaler Einsteiger. Vielen Dank für jede Hilfe.
Georg

: Bearbeitet durch User
von Chris B. (dekatz)


Lesenswert?

Georg G. schrieb:
>  Ich möchte die Spannungsversorgung des PICs über den I2C-Bus
>  machen ..........
>  Was nicht klappt, ist die Abfrage des analogen
> Ports. Ich simuliere auf dem Port RA0 eine Spannung zwischen 0 und 1 V.
> Wenn ich den Wert über I2C abfrage,

????????????????
Hier schein ein Verständnissproblem vorzuliegen: Wenn du An Port RA0 ein 
Spannung anlegst, der Port als Analogport definiert ist, dann bekommst 
du das Ergebniss der AD-Wandlung vom AD-Wandler des PIC und nicht von 
angeschlossenen I2C-Slave (was auch immer das für ein Chip ist).

Die Spannungsversorgung über den I2C-Bus????? wird wohl kaum 
funkteonieren!

Dann das hier:
>dataout VAR BYTE[8]    ' Data out array
und dann weiter mit:
>ADCIN 0, result     ' Read ADC channel 0
>dataout[4] = result

Mit "BYTE" sind ja offensichtlich 8-Bit-Daten definiert. Dann passt das 
Ergebniss einer AD-Wandlung mit 10 Bit ohnehin nicht rein - daher ist 
das Ergebniss im PIC auf 2 Register verteilt welche vom Anwender zu 
einem 10-Bit-Wert kombiniert werden müssen. Das würde auch erklären das 
du immer nur Werte zwischen 0...3 bekommst weil nur Bit 9+10 ausgewertet 
wird.
(Ich kenne PICBASIC und dessen Syntax nicht, kann also den Rest des 
Programms nicht ganz nachvollziehen - sorry)

Zuviel "Baustellen"!
Ein Schaltplan WAS den WO angeschlossen ist, was das für eine Messsonde 
ist und was am I2C-Bus hängt wäre ganz hilfreich um überhaupt ne 
Übersicht zu bekommen.

von Georg G. (Firma: ADV-Service) (mcgeorge)


Lesenswert?

Hallo Chris,
ich bin ä. bissl. blöd. Mit dem i2c-Bus meinte ich meinen 
Anschlussstecker. Das ist ein 6-pol Pfostenstecker mit 5 Volt 
Spannungsversorgung, i2c und 2 Reserveleitungen. Eine 
Spannungsversorgung über den i2c-Bus geht natürlich nicht.

Dein Hinweis mit 10-Bit und dem Byte-Wert war auf jeden fall der 
richtige Hinweis. Nachdem ich den Variablentyp der result-Variabel von 
BYTE auf WORD geändert hatte und die folgende Ergänzung gemacht hatte

dataout[4] = result.BYTE1
dataout[5] = result.BYTE0

,da ja dataout ein BYTE-ARRAY ist, hatte ich schon ein sinnvolleres 
Ergebnis.

Nur ist jetzt noch komisch, dass der Max-Wert 033F und nicht 03FF ist. 
Es scheint so als ob der BYTE0-Wert nicht größer als 3F wird. Das führt 
natürlich in der Zahlenfolge zu Sprüngen, wenn der Wert von 003F direkt 
auf 0100 springt.

Kann das noch an irgendwelchen Parametern für den PIC liegen, das die 
Bits 6+7 immer fehlen oder muss ich die Ursache in der 
Programmiersprache suchen?

Wie ist hier deine / Eure Meinung?

von Chris B. (dekatz)


Lesenswert?

Georg G. schrieb:
> Kann das noch an irgendwelchen Parametern für den PIC liegen, das die
> Bits 6+7 immer fehlen oder muss ich die Ursache in der
> Programmiersprache suchen?

Nein, der Fehler im Bit 6+7 hat nichts mit de6 Einstellung des ADC zu 
tun.
Schon eher das du die beiden Ergebnissbytes des ADC falsch 
interpretierst .....result VAR BYTE vs. result.BYTE0 und result.BYTE1 ?? 
was steht wo drinnen?? (btw. ich kenne den Compiler nicht).

Und noch etwas falls du den PIC mit +5V betreibst:
Laut DB ist für einen sicheren Betrieb des ADC eine MINIMALE positive 
Referenzspannung von 1,8V erforderlich. Also stelle die interen 
Referenzspannung auf 2,048V sonst sind alle Ergebnisse ziemlich 
fragwürdig
Die Angaben dazu finden sich im DB allgemein unter 
"DC-characteristics"...

(habe hier nur das DB eines 16F1503, aber so groß wird der Unterschied 
zum 16F1827 erfahrungsgemäß auch nicht sein....)

: Bearbeitet durch User
von Georg G. (Firma: ADV-Service) (mcgeorge)


Lesenswert?

Das mit den verschwundenen Bits habe ich durch umwandeln der HEX-Werte 
in Dezimalzahlen umgangen. Die Bits verlieren sich bei der Übertragung 
über i2c. Suche ich später, wenn ich mehr Zeit habe.

Aber noch eine Frage, Du hast geschrieben, dass ich die FVR auf 2,048 V 
einstellen soll, um verläßliche Ergebnisse zu erhalten.

Bedeutet es, dass die interne Referenzspannung von 1,024 V für den ADC 
überhaupt nicht zu verwenden ist?

Oder ist es abhängig von der Betriebsspannung (5 oder 3 Volt)?

Danke schon mal für alle bisherigen Tipps.

von Chris B. (dekatz)


Lesenswert?

Georg G. schrieb:
> Aber noch eine Frage, Du hast geschrieben, dass ich die FVR auf 2,048 V
> einstellen soll, um verläßliche Ergebnisse zu erhalten.
>
> Bedeutet es, dass die interne Referenzspannung von 1,024 V für den ADC
> überhaupt nicht zu verwenden ist?
>
> Oder ist es abhängig von der Betriebsspannung (5 oder 3 Volt)?
>

Jetzt habe ich beim 16F1827 nagesehen. Die 1,024V Referenz für den ADC 
sollte ab 2,5V Vdd funkteonieren (vorhin hatte ichnur das DB vom 16F1503 
greifbar)
Allerdings ist die Vref nicht exakt 1,024V/2,048V/4,06V sondern kann um
-8...+6% von den angegebenen Werten abweichen!

Datenblatt ->>> Kapitel 30.1, 30.8 und 30.9 beachten !!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.