Op 14 juni 2021 00:03:46 schreef PE9SMS:
[...]Dat zal wel de DHT22 zijn die je voor ogen hebt? De SHT21 is een sensor van Sensirion.
Yep, die bedoel ik. Sorry. Foutje!
Op 14 juni 2021 00:03:46 schreef PE9SMS:
[...]Dat zal wel de DHT22 zijn die je voor ogen hebt? De SHT21 is een sensor van Sensirion.
Yep, die bedoel ik. Sorry. Foutje!
Golden Member
Hoe verhoudt een MCP9801 zich eigenlijk tot de SHT21 (even alleen m.b.t. de temperatuur, de MCP9801 heeft geen RH).
Beiden I2C protocol.
Of is de keuze gewoon arbitrair?
Special Member
Dat is een kwestie van de datasheets naast elkaar leggen. Nauwkeurigheid, resolutie en bereik lijken me de interessantste parameters.
Special Member
MCP980x is 0.0625°/0.5° en de SHT21 is 0.01°/0.3° resolution/accuracy
Golden Member
Golden Member
Ik heb de SHT21 aan de praat.
Het is een 14-bits resolutie. Dus samenvoegen van Hi (Eerste read) en Lo (Tweede read) en dan alles 2 naar rechts schuiven.
Maar het is wel lastig om de omrekenformule in MikroBasic te zetten:
De formule van de SHT21 is:
Ik had dat door:
pic basic code:
Dim Temp2 as Longword
---
---
Temp2 = Temp>>2
Temp2 = -46.85 + (175.72 * Temp)
Temp2 = Temp2 >> 14
LongWordToStr(Temp2, StrTot)
Lcd_String_8x16(0, 5, "Temp2: " + StrTot)
Maar dit gaat dus niet lekker.
Ik kan het wel voor elkaar krijgen, maar dan moet ik een heleboel tussenresultaten opnemen.
Hoe kan dit nu op een slimme manier?
Special Member
Temp2 moet een float zijn. Je kunt het resultaat van een berekening met gebroken getallen niet in een integer opslaan. (zonder veel verlies)
Golden Member
Op 14 juni 2021 16:20:48 schreef Arco:
Temp2 moet een float zijn. Je kunt het resultaat van een berekening met gebroken getallen niet in een integer opslaan. (zonder veel verlies)
Ik heb het nu zo:
pic basic code:
Dim Temp As Word
Temp2 As Float
Temp3 As Float
StrHi As string[5]
StrLo As string[5]
StrTot As String[9]
---
---
Main:
While True
While (I2C1_Is_Idle) = 0 wend 'Wait till bus ready
I2C1_Start() 'Start
I2C1_Wr(0x80) 'SHT write address
I2C1_Wr(%11100011) 'Command Measure Temp
I2C1_Repeated_Start() 'Bus restart
I2C1_Wr(0x81) 'SHT read address
Hi(Temp) = I2C1_Rd(1)
Lo(Temp) = I2C1_Rd(1)
CheckSum = I2C1_Rd(0) 'Stop after Checksum
I2C1_Stop() 'Stop
Delay_ms(5)
Temp2 = Temp >>2
Temp3 = -46.85 + (175.72 * Temp2) / 16384
FloatToStr(Temp3, StrTot)
Lcd_String_8x16(0, 1, "Temp: " + StrTot)
Delay_Ms(5000)
Wend
Het lijkt te werken (wel een hoge temp waarde), maar mijn gevoel zegt dat hier iets dubbel zit (of niet goed)...
Op 14 juni 2021 17:11:21 schreef Bavelt:
pic basic code:
Temp2 = Temp >>2 Temp3 = -46.85 + (175.72 * Temp2) / 16384
Dit kan iets korter. In de eerste regel deel je "Temp" door 4 en slaat dat in de variabele "Temp2" op. Daarna ga je temp2 met 175 vermenigvuldigen en dan delen door 16384. Tja Dat kan je allemaal "vantevoren" doen:
Temp3 = -46.85 + (175.72/4/16384) * Temp
Ik hoop dat de compiler het stuk tussen de haakjes vantevoren 1x uitrekent, om heel zeker te weten dat ie dit niet runtime gaat uitrekenen zou je het getal met een rekenmachine kunnen uitrekenen.
(maar een moderne compiler gaat echt wel zien dat ie dit op je PC alvastkan uitrekenen zodat de PIC dat straks niet hoeft te doen. )
(Anderzijds, in de PIC wereld schijnt het normaal te zijn dat je compiler-zonder-optimalisatie krijgt en moet betalen voor de optimalisaties....).
P.S. Als je jou code makkelijker te lezen vind, dan is dat eigenlijk belangrijker dan dat het efficienter of korter kan.
Special Member
Als je de originele regels gebruikt, moet er wel een implicit conversion bij (float), anders is de uitkomst onzeker.
Omdat er door een integer wordt gedeeld (16384) rondt de compiler het resultaal ook af als integer.
pic basic code:
Temp2 = Temp >>2
Temp3 = float(-46.85 + (175.72 * Temp2) / 16384)
wat ook kan is een float van 16384 te maken door er .0 achter te zetten. (16384 is voor de compiler niet hetzelfde als 16384.0)
pic basic code:
Temp2 = Temp >>2
Temp3 = -46.85 + (175.72 * Temp2) / 16384.0
Golden Member
Er zit nog een vervelend foutje in het programma. Ik zie niet waar het fout gaat.
Update: is opgelost.
Ik heb het nu zo:
pic basic code:
'====================================================================================================
Sub Function SHT21_Read(Dim pAdr As Byte, Dim pReg As Byte) As Word 'Read SHT21
'====================================================================================================
While (I2C1_Is_Idle) = 0 wend
I2C1_Start() 'Start
I2C1_Wr(pAdr) 'SHT write address
I2C1_Wr(pReg)
I2C1_Repeated_Start() 'Bus restart
I2C1_Wr(pAdr + 1) 'SHT21 read address
Hi(Result) = I2C1_Rd(1)
Lo(Result) = I2C1_Rd(0)
'CheckSum = I2C1_Rd(0)
I2C1_Stop() 'Stop
delay_ms(5) 'Wait to complete
End Sub
----
----
Main:
While True
Temp = SHT21_Read(0x80, %11100011) 'Command measure Temperature
BytetoStr(Hi(Temp), StrHi)
BytetoStr(Lo(Temp), StrLo)
Lcd_String_8x16(0, 1, "Temp: " + StrHi + " , " + StrLo)
Temp2 = Temp >>2
Temp3 = float(-46.85 + (175.72 * Temp2) / 16384)
FloatToStr(Temp3, StrTot)
Lcd_String_8x16(0, 3, "Temp: " + StrTot)
Delay_Ms(1000)
Wend
Ik weet alleen niet of ik het goed heb gedaan met de Checksum. Die gebruik ik niet. De (0) in Lo(Result) = I2C1_Rd(0) geeft toch aan laatste read?
Op 14 juni 2021 20:27:50 schreef Arco:
Als je de originele regels gebruikt, moet er wel een implicit conversion bij (float), anders is de uitkomst onzeker.
Omdat er door een integer wordt gedeeld (16384) rondt de compiler het resultaal ook af als integer.pic basic code:
Temp2 = Temp >>2 Temp3 = float(-46.85 + (175.72 * Temp2) / 16384)
]
1: Je hebt de haakjes verkeerd gezet. de minimale te meten temp is -46 graden, de totale range is 175 graden en de gemeten waarde moet je als 0.xxxxxx BINAIR zien, dus als een getal tussen 0 en 1.
2) jou aanpassing converteert wat de compiler als resultaat heeft van de berekening naar float voordat ie aan "Temp3" wordt toegekend. Dat is een conversie die vanzelf/altijd gebeurt als je een assignment aan een float variabele doet. Vergelijk Temp3 = 100/3 . De temp3 variabele krijgt nu de waarde 33.00 net als bij Temp3 = float (100/3) . Je bedoelt Temp3 = float(100)/float(3) .
2: Ik zou denken dat als je zeg 12.34 / 2 doet, dit een float blijft.
Dus 175.72*<int> is een float, float / int is een float.
Maar of dat in (die variant van) basic ook zo is, weet ik niet.
Ik weet alleen niet of ik het goed heb gedaan met de Checksum. Die gebruik ik niet. De (0) in Lo(Result) = I2C1_Rd(0) geeft toch aan laatste read?
Right! Na iedere byte kan je op i2c aangeven aan de "gesprekspartner", van "en hierna wil ik graag nog een byte". Maar je mag aangeven: nog 1 is prima, en dan toch ophouden met vragen (STOP). Dus voor het gemak kan je altijd "1" doorgeven, zodat je niet de bestaande regel hoeft te veranderen als je in de toekomst de checksum zou willen gaan lezen en gebruiken.
[Bericht gewijzigd door rew op dinsdag 15 juni 2021 08:31:36 (18%)
Special Member
Bij veel compilers (ook deze) is het resultaat een integer als er een integer in de berekening zit, ongeacht het type variabele van de bestemming.
(ik vind het krom, maar C compilers schijnen dat ook te doen)
Met 16384.0 is het probleem ook weg dus.
[Bericht gewijzigd door Arco op dinsdag 15 juni 2021 09:31:16 (11%)
Op 15 juni 2021 09:30:27 schreef Arco:
(ik vind het krom, maar C compilers schijnen dat ook te doen)
Nee. In C is 100.0 / 3 de float 33.33... (*)
Je kan het zo zien: a / b is een verkorte notatie voor "div (a, b)".
De functie "div" heeft een aantal prototypes:
int div (int a, int b)
float div (float a, float b)
Hierbij wordt net als bij float factor = 1; een "upgrade" gedaan wordt als er een int opgegeven is waar een float verwacht werd. Daarmee matched dus 100.0 / 3 dus met het tweede prototype, waarbij de b parameter van int naar float moet worden gepromoveerd voordat die aan de functie "div" kan worden doorgegeven.
(*) In C hebben ze lang geleden een rare beslissing genomen: Alle floating point berekeningen moeten in double, niet in float. Dus waar ik hier "float" zeg is het strict genomen "double".
[Bericht gewijzigd door rew op dinsdag 15 juni 2021 10:46:26 (12%)
Golden Member
Op 15 juni 2021 08:27:53 schreef rew:
Right! Na iedere byte kan je op i2c aangeven aan de "gesprekspartner", van "en hierna wil ik graag nog een byte". Maar je mag aangeven: nog 1 is prima, en dan toch ophouden met vragen (STOP). Dus voor het gemak kan je altijd "1" doorgeven, zodat je niet de bestaande regel hoeft te veranderen als je in de toekomst de checksum zou willen gaan lezen en gebruiken.
Dat zou betekenen dat:
pic basic code:
Hi(Result) = I2C1_Rd(1)
Lo(Result) = I2C1_Rd(1)
I2C1_Stop()
Zou moeten werken. Toch is dat niet zo: als ik niet met een (0) eindig, hangt het de boel op...
Special Member
Laatste busread moet altijd met een 'NACK' worden afgesloten. Sommige slaves raken anders overstuur en hangen.
(processor geeft daarmee aan 'ik ben klaar')
[Bericht gewijzigd door Arco op dinsdag 15 juni 2021 11:55:28 (17%)
Golden Member
Nou, dit is het uiteindelijk geworden.
Voor de liefhebber.
pic basic code:
'====================================================================================================
Program SHT21_1847
'====================================================================================================
' Project name: SHT21_1847
' MCU: PIC16F1847
' Oscillator: Internal 8 MHz
' Display: Oled SPI 0,96"
' Temp Sensor SHT21
' SDO2: LAT A.0 Pin 17
' SCK2: PORT B.5 Pin 11
' SDA1: PORT B.1 Pin 7
' SCL1: PORT B.4 Pin 10
' D/C: LAT B.0 Pin 6
' CS: LAT A.4 Pin 3
' RES: LAT B.3 Pin 9
'====================================================================================================
Const Dos8x16ext As Byte [1520]= (
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, '
0x00,0x00,0x00,0xFC,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x33,0x00,0x00,0x00, ' !
0x00,0xF3,0xF3,0x00,0x00,0xF3,0xF3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ' "
0x30,0xF3,0xF3,0x30,0x30,0xF3,0xF3,0x30,0x03,0x0F,0x0F,0x03,0x03,0x0F,0x0F,0x03, ' #
0x00,0x78,0xF3,0xCF,0xCF,0xCC,0x8C,0x00,0x00,0x0C,0x0C,0x3C,0x3C,0x0F,0x07,0x00, ' $
0x00,0x1C,0x1C,0xC0,0xF0,0x3C,0x0C,0x00,0x00,0x0C,0x0F,0x03,0x00,0x0E,0x0E,0x00, ' %
0x00,0xD8,0xFC,0xCC,0x7C,0x18,0x00,0x00,0x1F,0x3F,0x31,0x33,0x1F,0x3F,0x33,0x00, ' &
0x00,0x00,0x00,0xFC,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ' '
0x00,0x00,0x00,0xF0,0xF8,0x1C,0x04,0x00,0x00,0x00,0x00,0x0F,0x1F,0x38,0x20,0x00, ' (
0x00,0x04,0x1C,0xF8,0xF0,0x00,0x00,0x00,0x00,0x20,0x38,0x1F,0x0F,0x00,0x00,0x00, ' )
0xC0,0xCC,0xFC,0xF0,0xF0,0xFC,0xCC,0xC0,0x00,0x0C,0x0F,0x03,0x03,0x0F,0x0C,0x00, ' *
0x00,0xC0,0xC0,0xF8,0xF8,0xC0,0xC0,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, ' +
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x7C,0x3C,0x00,0x00,0x00, ' ,
0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ' -
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x00,0x00,0x00, ' .
0x00,0x00,0x00,0x80,0xE0,0x7C,0x1C,0x00,0x00,0x38,0x3E,0x07,0x01,0x00,0x00,0x00, ' /
0x00,0xF8,0xFC,0x0C,0x8C,0xFC,0xF8,0x00,0x00,0x1F,0x3F,0x31,0x30,0x3F,0x1F,0x00, ' 0
0x00,0x00,0x30,0xFC,0xFC,0x00,0x00,0x00,0x00,0x30,0x30,0x3F,0x3F,0x30,0x30,0x00, ' 1
0x00,0x38,0x3C,0x0C,0xCC,0xFC,0x38,0x00,0x00,0x30,0x3C,0x3F,0x33,0x30,0x30,0x00, ' 2
0x00,0x0C,0x0C,0xCC,0xFC,0x3C,0x0C,0x00,0x00,0x1C,0x3C,0x30,0x33,0x3F,0x1C,0x00, ' 3
0x00,0x00,0xC0,0xF0,0xFC,0xFC,0x00,0x00,0x00,0x0F,0x0F,0x0C,0x3F,0x3F,0x0C,0x00, ' 4
0x00,0xFC,0xFC,0xCC,0xCC,0xCC,0x8C,0x00,0x00,0x18,0x38,0x30,0x30,0x3F,0x1F,0x00, ' 5
0x00,0xF0,0xF8,0x9C,0x8C,0x8C,0x00,0x00,0x00,0x1F,0x3F,0x31,0x31,0x3F,0x1F,0x00, ' 6
0x00,0x0C,0x0C,0x0C,0xCC,0xFC,0x3C,0x00,0x00,0x00,0x3C,0x3F,0x03,0x00,0x00,0x00, ' 7
0x00,0x38,0xFC,0xCC,0xCC,0xFC,0x38,0x00,0x00,0x1F,0x3F,0x30,0x30,0x3F,0x1F,0x00, ' 8
0x00,0x78,0xFC,0xCC,0xCC,0xFC,0xF8,0x00,0x00,0x00,0x30,0x30,0x38,0x1F,0x0F,0x00, ' 9
0x00,0x00,0x00,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x00,0x00,0x00, ' :
0x00,0x00,0x00,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0xC0,0x7C,0x3C,0x00,0x00,0x00, ' ;
0x80,0xC0,0xE0,0x70,0x38,0x18,0x08,0x00,0x00,0x01,0x03,0x07,0x0E,0x0C,0x08,0x00, ' <
0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x00, ' =
0x08,0x18,0x38,0x70,0xE0,0xC0,0x80,0x00,0x08,0x0C,0x0E,0x07,0x03,0x01,0x00,0x00, ' >
0x00,0x38,0x3C,0x0C,0xCC,0xFC,0x38,0x00,0x00,0x00,0x00,0x37,0x37,0x00,0x00,0x00, ' ?
0xF0,0xF8,0x1C,0xCC,0x4C,0x98,0xF0,0x00,0x0F,0x1F,0x38,0x33,0x32,0x33,0x19,0x00, ' @
0x00,0xF0,0xF8,0x1C,0x1C,0xF8,0xF0,0x00,0x00,0x3F,0x3F,0x03,0x03,0x3F,0x3F,0x00, ' A
0x00,0xFC,0xFC,0xCC,0xCC,0xFC,0x78,0x00,0x00,0x3F,0x3F,0x30,0x30,0x3F,0x1F,0x00, ' B
0x00,0xF8,0xFC,0x0C,0x0C,0x3C,0x38,0x00,0x00,0x1F,0x3F,0x30,0x30,0x3C,0x1C,0x00, ' C
0x00,0xFC,0xFC,0x0C,0x1C,0xF8,0xF0,0x00,0x00,0x3F,0x3F,0x30,0x38,0x1F,0x0F,0x00, ' D
0x00,0xFC,0xFC,0xCC,0xCC,0xCC,0x0C,0x00,0x00,0x3F,0x3F,0x30,0x30,0x30,0x30,0x00, ' E
0x00,0xFC,0xFC,0xCC,0xCC,0xCC,0x0C,0x00,0x00,0x3F,0x3F,0x00,0x00,0x00,0x00,0x00, ' F
0x00,0xF8,0xFC,0x0C,0xCC,0xCC,0xCC,0x00,0x00,0x1F,0x3F,0x30,0x30,0x3F,0x1F,0x00, ' G
0x00,0xFC,0xFC,0xC0,0xC0,0xFC,0xFC,0x00,0x00,0x3F,0x3F,0x00,0x00,0x3F,0x3F,0x00, ' H
0x00,0x0C,0x0C,0xFC,0xFC,0x0C,0x00,0x00,0x00,0x30,0x30,0x3F,0x3F,0x30,0x00,0x00, ' I
0x00,0x00,0x00,0x00,0x00,0xFC,0xFC,0x00,0x00,0x1C,0x3C,0x30,0x30,0x3F,0x1F,0x00, ' J
0xFC,0xFC,0xC0,0xF0,0x3C,0x0C,0x00,0x00,0x3F,0x3F,0x00,0x03,0x0F,0x3C,0x30,0x00, ' K
0x00,0xFC,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x3F,0x30,0x30,0x30,0x30,0x00, ' L
0xFC,0xFC,0x70,0xC0,0x70,0xFC,0xFC,0x00,0x3F,0x3F,0x00,0x01,0x00,0x3F,0x3F,0x00, ' M
0x00,0xFC,0xFC,0xE0,0x80,0xFC,0xFC,0x00,0x00,0x3F,0x3F,0x01,0x07,0x3F,0x3F,0x00, ' N
0x00,0xF8,0xFC,0x0C,0x0C,0xFC,0xF8,0x00,0x00,0x1F,0x3F,0x30,0x30,0x3F,0x1F,0x00, ' O
0x00,0xFC,0xFC,0x0C,0x0C,0xFC,0xF8,0x00,0x00,0x3F,0x3F,0x03,0x03,0x03,0x01,0x00, ' P
0x00,0xF8,0xFC,0x0C,0x0C,0xFC,0xF8,0x00,0x00,0x1F,0x3F,0x38,0x1E,0x3F,0x37,0x00, ' Q
0xFC,0xFC,0x8C,0x8C,0xFC,0xF8,0x00,0x00,0x3F,0x3F,0x01,0x03,0x0F,0x3C,0x30,0x00, ' R
0x00,0x78,0xFC,0xCC,0x8C,0x8C,0x18,0x00,0x00,0x18,0x31,0x31,0x33,0x3F,0x1E,0x00, ' S
0x00,0x0C,0x0C,0xFC,0xFC,0x0C,0x0C,0x00,0x00,0x00,0x00,0x3F,0x3F,0x00,0x00,0x00, ' T
0x00,0xFC,0xFC,0x00,0x00,0xFC,0xFC,0x00,0x00,0x1F,0x3F,0x30,0x30,0x3F,0x1F,0x00, ' U
0x00,0xFC,0xFC,0x00,0x00,0xFC,0xFC,0x00,0x00,0x03,0x0F,0x3C,0x3C,0x0F,0x03,0x00, ' V
0xFC,0xFC,0x00,0x80,0x00,0xFC,0xFC,0x00,0x3F,0x1F,0x0E,0x07,0x0E,0x1F,0x3F,0x00, ' W
0x00,0x1C,0x7C,0xE0,0xE0,0x7C,0x1C,0x00,0x00,0x38,0x3E,0x07,0x07,0x3E,0x38,0x00, ' X
0x00,0x3C,0xFC,0xC0,0xC0,0xFC,0x3C,0x00,0x00,0x00,0x00,0x3F,0x3F,0x00,0x00,0x00, ' Y
0x00,0x0C,0x0C,0xCC,0xFC,0x3C,0x0C,0x00,0x00,0x3C,0x3F,0x33,0x30,0x30,0x30,0x00, ' Z
0x00,0x00,0x00,0xFC,0xFC,0x0C,0x0C,0x00,0x00,0x00,0x00,0x3F,0x3F,0x30,0x30,0x00, ' [
0x00,0x0C,0x0C,0xFC,0xFC,0x00,0x00,0x00,0x00,0x30,0x30,0x3F,0x3F,0x00,0x00,0x00, ' \
0x80,0xE0,0x78,0x1E,0x78,0xE0,0xE0,0x00,0x01,0x01,0x00,0x00,0x00,0x01,0x01,0x00, ' ]
0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ' ^
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00, ' _
0x00,0x07,0x0E,0x1C,0x38,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ' `
0x00,0x00,0x60,0x60,0x60,0xE0,0xC0,0x00,0x00,0x1E,0x3F,0x33,0x33,0x3F,0x3F,0x00, ' a
0x00,0xFC,0xFC,0x60,0x60,0xE0,0xC0,0x00,0x00,0x3F,0x3F,0x30,0x30,0x3F,0x1F,0x00, ' b
0x00,0xC0,0xE0,0x60,0x60,0x60,0x00,0x00,0x00,0x1F,0x3F,0x30,0x30,0x30,0x30,0x00, ' c
0x00,0xC0,0xE0,0x60,0x60,0xFC,0xFC,0x00,0x00,0x1F,0x3F,0x30,0x30,0x3F,0x3F,0x00, ' d
0x00,0xC0,0xE0,0x60,0x60,0xE0,0xC0,0x00,0x00,0x1F,0x3F,0x32,0x32,0x33,0x33,0x00, ' e
0x00,0xC0,0xC0,0xF8,0xFC,0xCC,0xCC,0x00,0x00,0x00,0x00,0x3F,0x3F,0x00,0x00,0x00, ' f
0x00,0xC0,0xE0,0x60,0x60,0xE0,0xE0,0x00,0x00,0xCF,0xDF,0xD8,0xD8,0xFF,0x7F,0x00, ' g
0x00,0xFC,0xFC,0x60,0x60,0xE0,0xC0,0x00,0x00,0x3F,0x3F,0x00,0x00,0x3F,0x3F,0x00, ' h
0x00,0x00,0x60,0xEC,0xEC,0x00,0x00,0x00,0x00,0x00,0x30,0x3F,0x3F,0x30,0x00,0x00, ' i
0x00,0x00,0x00,0x00,0xEC,0xEC,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xFF,0x7F,0x00,0x00, ' j
0xFC,0xFC,0x80,0xC0,0xE0,0x60,0x00,0x00,0x3F,0x3F,0x03,0x07,0x1E,0x38,0x30,0x00, ' k
0x00,0x00,0x0C,0xFC,0xFC,0x00,0x00,0x00,0x00,0x00,0x30,0x3F,0x3F,0x30,0x00,0x00, ' l
0xC0,0xE0,0xE0,0xC0,0xE0,0xE0,0xC0,0x00,0x3F,0x3F,0x00,0x07,0x00,0x3F,0x3F,0x00, ' m
0x00,0xC0,0xE0,0x60,0x60,0xE0,0xC0,0x00,0x00,0x3F,0x3F,0x00,0x00,0x3F,0x3F,0x00, ' n
0x00,0xC0,0xE0,0x60,0x60,0xE0,0xC0,0x00,0x00,0x1F,0x3F,0x30,0x30,0x3F,0x1F,0x00, ' o
0x00,0xE0,0xE0,0x60,0x60,0xE0,0xC0,0x00,0x00,0xFF,0xFF,0x30,0x30,0x3F,0x1F,0x00, ' p
0x00,0xC0,0xE0,0x60,0x60,0xE0,0xE0,0x00,0x00,0x1F,0x3F,0x30,0x30,0xFF,0xFF,0x00, ' q
0x00,0xE0,0xE0,0x60,0x60,0xE0,0xC0,0x00,0x00,0x3F,0x3F,0x00,0x00,0x00,0x00,0x00, ' r
0x00,0xC0,0xE0,0x60,0x60,0x60,0x60,0x00,0x00,0x31,0x33,0x33,0x36,0x3E,0x3C,0x00, ' s
0x00,0x60,0x60,0xF8,0xF8,0x60,0x60,0x00,0x00,0x00,0x00,0x1F,0x3F,0x30,0x30,0x00, ' t
0x00,0xE0,0xE0,0x00,0x00,0xE0,0xE0,0x00,0x00,0x1F,0x3F,0x30,0x30,0x3F,0x3F,0x00, ' u
0x00,0xE0,0xE0,0x00,0x00,0xE0,0xE0,0x00,0x00,0x03,0x0F,0x3C,0x3C,0x0F,0x03,0x00, ' v
0xE0,0xE0,0x00,0x80,0x00,0xE0,0xE0,0x00,0x3F,0x1F,0x0E,0x07,0x0E,0x1F,0x3F,0x00, ' w
0x00,0x60,0xE0,0x80,0x80,0xE0,0x60,0x00,0x00,0x30,0x3D,0x0F,0x0F,0x3D,0x30,0x00, ' x
0x00,0xE0,0xE0,0x00,0x00,0xE0,0xE0,0x00,0x00,0xCF,0xDF,0xD8,0xD8,0xFF,0x7F,0x00, ' y
0x00,0x60,0x60,0x60,0xE0,0xE0,0x60,0x00,0x00,0x30,0x3C,0x3F,0x33,0x30,0x30,0x00, ' z
0x80,0x80,0xC0,0xFC,0x7E,0x02,0x02,0x00,0x01,0x01,0x03,0x3F,0x7E,0x40,0x40,0x00, ' {
0x00,0x00,0x00,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x7F,0x00,0x00,0x00, ' |
0x02,0x02,0x7E,0x7C,0xC0,0x80,0x80,0x00,0x40,0x40,0x7E,0x3F,0x03,0x01,0x01,0x00, ' }
0xC0,0x60,0xE0,0xC0,0x80,0x80,0xE0,0x00,0x01,0x00,0x00,0x01,0x01,0x01,0x00,0x00) ' ~
'
Address As Byte = 0x80
Temparature As Byte = %11100011
Humidity As Byte = %11100101
Dim SCKPin As sbit at PORTB.5 'pin 11 'SCK - SPI2
SDOPin As sbit at LATA.0 'pin 17 'SDO - SPI2
SCLPin As sbit at PORTB.1 'pin 7 'SCL - I2C1
SDAPin As sbit at PORTB.4 'pin 10 'SDA - I2C1
D_C As sBit at LATB.0 'pin 6 'Data/Command
C_S As sbit at LATA.4 'pin 3 'Chip Select
RES As sbit at LATB.3 'pin 9 'Reset Display
Temp As Word
Temp2 As Float
Temp3 As Float
StrHi As string[5]
StrLo As string[5]
StrTot As String[5]
CheckSum As Byte
'====================================================================================================
Sub Function SHT21_Read(Dim pAdr As Byte, Dim pReg As Byte) As Word 'Read SHT21
'====================================================================================================
While (I2C1_Is_Idle) = 0 wend
I2C1_Start() 'Start I2C
I2C1_Wr(pAdr) 'SHT21 write address
I2C1_Wr(pReg)
I2C1_Repeated_Start() 'Bus restart
I2C1_Wr(pAdr + 1) 'SHT read address
Hi(Result) = I2C1_Rd(1)
Lo(Result) = I2C1_Rd(0)
'CheckSum = I2C1_Rd(0) 'CheckSum not used
I2C1_Stop() 'Stop I2C
delay_ms(5) 'Wait to complete
End Sub
'====================================================================================================
Sub Procedure Lcd_WrCmd(Dim pCmd As Byte) 'Write command to display
'====================================================================================================
D_C = 0
SPI2_Write(pCmd)
End Sub
'====================================================================================================
Sub Procedure Lcd_WrDat(Dim pDat As Byte) 'Write data to display
'====================================================================================================
Dim lCnt As Byte
D_C = 1
SPI2_Write(pDat)
End Sub
'====================================================================================================
Sub Procedure Lcd_SetPos(Dim px, py as Byte) 'Set write position on display
'====================================================================================================
Delay_us(1)
Lcd_WrCmd(0xB0 + py)
Lcd_WrCmd((px >> 4) Or 0x10)
Lcd_WrCmd((px And 0x0F))
delay_ms(1)
End Sub
'====================================================================================================
Sub Procedure Lcd_Fill(Dim pFill As Byte) 'Fill display with character pFill
'====================================================================================================
Dim lx, ly As Byte
For ly = 0 To 7
Lcd_WrCmd(0xB0+ly)
Lcd_WrCmd(0x00)
Lcd_WrCmd(0x10)
For lx = 0 to 127
Lcd_WrDat(pFill)
Next lx
Next ly
End Sub
'====================================================================================================
Sub Procedure Lcd_Char_8x16(Dim px, py, pchar As Byte)
'====================================================================================================
Dim lIndex As Word
lIndex = pChar - 0x20
lIndex = (lIndex << 4)
Lcd_SetPos(px, py)
Lcd_WrDat(Dos8x16ext[lIndex+0])
Lcd_WrDat(Dos8x16ext[lIndex+1])
Lcd_WrDat(Dos8x16ext[lIndex+2])
Lcd_WrDat(Dos8x16ext[lIndex+3])
Lcd_WrDat(Dos8x16ext[lIndex+4])
Lcd_WrDat(Dos8x16ext[lIndex+5])
Lcd_WrDat(Dos8x16ext[lIndex+6])
Lcd_WrDat(Dos8x16ext[lIndex+7])
Lcd_SetPos(px, py+1)
Lcd_WrDat(Dos8x16ext[lIndex+8])
Lcd_WrDat(Dos8x16ext[lIndex+9])
Lcd_WrDat(Dos8x16ext[lIndex+10])
Lcd_WrDat(Dos8x16ext[lIndex+11])
Lcd_WrDat(Dos8x16ext[lIndex+12])
Lcd_WrDat(Dos8x16ext[lIndex+13])
Lcd_WrDat(Dos8x16ext[lIndex+14])
Lcd_WrDat(Dos8x16ext[lIndex+15])
End Sub
'====================================================================================================
Sub Procedure Lcd_String_8x16(Dim px, py As Byte, Dim ByRef pDisp As String)
'====================================================================================================
Dim lLen, lCnt As Byte
lLen = Length(pDisp)
For lCnt = 0 To (lLen-1)
Lcd_Char_8x16(px+1, py, pDisp[lCnt])
px = px + 8
Next lCnt
End Sub
'====================================================================================================
Sub Procedure Display_Init()
'====================================================================================================
Lcd_WrCmd(0xAF) 'Turn OLED panel off
Lcd_WrCmd(0xA8) 'Multiplex ratio set to
Lcd_WrCmd(0x3F) '63
Lcd_WrCmd(0xD3) 'Display offset RAM counter
Lcd_WrCmd(0x00) 'none
Lcd_WrCmd(0x40) 'Start line address
Lcd_WrCmd(0xA1) 'Set segment remap rotation to left
Lcd_WrCmd(0xC8) 'Common output scan direction
Lcd_WrCmd(0xDA) 'Common signals pad
Lcd_WrCmd(0x12) 'value
Lcd_WrCmd(0x81) 'Contrast control
Lcd_WrCmd(0xFF) 'value
Lcd_WrCmd(0xA4)
Lcd_WrCmd(0xA6) 'Normal display
Lcd_WrCmd(0xD5) 'Clock ratio:oscillator frequency
Lcd_WrCmd(0x80) 'oooo:rrrr
Lcd_WrCmd(0x8D)
Lcd_WrCmd(0x14)
Lcd_WrCmd(0x00) 'Set lower column address
Lcd_WrCmd(0x10) 'Set higher column address
Lcd_WrCmd(0xD9) '15 clocks, discharge 1 clock
Lcd_WrCmd(0xF1) 'dddd:pppp
Lcd_WrCmd(0xDB) 'Common output voltage
Lcd_WrCmd(0x40) 'level
Lcd_WrCmd(0x20) 'Addressing mode
Lcd_WrCmd(0x02) 'value
Lcd_WrCmd(0xAE) 'Turn OLED panel off
End Sub
'====================================================================================================
Main: 'Main program
'====================================================================================================
ANSELA = %00000000 'All Port A digital
ANSELB = %00000000 'All Port B digital
TRISA = %10101100 'A.2, A.3, A5 A.7 Input
TRISB = %00010010 'B.1, B.4 Input
OSCCON = %01110000 '8Mhz internal
StrHi = " "
StrLo = " "
StrTot = " "
I2C1_init(100000) 'Init I2C1 port 100kHz
C_S = 1
RES = 0 'Reset Display
Delay_ms(500)
RES = 1
C_S = 0
SPI2_Init()
Delay_ms(100)
Display_Init()
Delay_ms(100)
Lcd_WrCmd(0xAF) 'Turn OLED panel on
LCD_Setpos(0,0) 'Set start Position
LCD_Fill(0x00) 'Blank Screen
Delay_ms(50)
While True
Temp = SHT21_Read(Address, Temparature) 'Read Temperature
Temp2 = Temp >>2 '14 bits Resolution
Temp3 = -46.85 + (175.72 * Temp2) / 16384.0
FloatToStr(Temp3, StrTot)
Rtrim(StrTot)
Lcd_String_8x16(0, 1, "Temp: " + StrTot)
Temp = SHT21_Read(Address, Humidity) 'Read Humidity
Temp2 = Temp >>4 '12 bits Resolution
Temp3 = -6 + (125 * Temp2) / 4096.0
FloatToStr(Temp3, StrTot)
Lcd_String_8x16(0, 5, "RH: " + StrTot + "%")
Delay_Ms(1000)
Wend
End.