OLED display met ST7789 en MikroBasic

Bavelt

Golden Member

Het verbaast me trouwens dat in deze tutorial de SDA en SCL gewoon aan de PIC16F877A worden gehangen, terwijl de VDD +5 Volt is..

Update: Te voorbarig gepost! Ik zie nu dat dit een moduultje is met Voltage regulator en Level shifter aan boord...

[Bericht gewijzigd door Bavelt op woensdag 8 april 2020 21:49:17 (44%)

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Ik kwam tot zoiets, maar dat geeft steeds waarde 128 terug

pic basic code:

Sub Function BME280_Read(Dim preg as Byte) as Byte
 
 While Not (i2c1_Is_Idle) wend
  i2c1_Start()                                                      'Start
  i2c1_Wr(0xEC)                                                     'MCP write address
  i2c1_Wr(pReg)
  i2c1_Repeated_Start()                                             'Bus restart
  i2c1_Wr(0xED)
  Result = i2c1_rd(0)
  i2c1_Stop()
End Sub

en

pic basic code:

TempB = BME280_Read(0xFA)
    ByteToStr(TempB, StrB)
    lTrim(StrB)

   Lcd_String_8x16 (0, 6, "BME280: " + StrB)

De tabel uit de Datasheet:

Ik weet niet goed hoe ik het ding nu moet configureren...

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Ik begrijp die tabel niet erg. Er staat dat register 0xFA na reset de waarde 0x80 heeft. Daar hoort toch de actuele temperatuur in te staan?
Dat je 128 uitleest (= 0x80) klopt dan weer wel...

't ding start op in sleep-mode... (handig :( )
Je moet dan register 0xF4 op 0x03 zetten.

[Bericht gewijzigd door Arco op woensdag 8 april 2020 22:51:44 (19%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Ik heb er zoiets van genaakt:

pic basic code:

Sub Procedure BME280_Write(Dim pReg as Byte, dim InData as Byte)
  While Not (I2C1_Is_Idle) Wend
  I2C1_Start()                                                      'Start
  I2C1_Wr(0xEC)                                                     'Write adress
  I2C1_Wr(pReg)
  I2C1_Wr(InData)
  I2C1_Stop()
End Sub

en

pic basic code:

BME280_Write(0xF4, 0x03)                        'Start Normal

Ik vraag me ook af of ik het goede register wl pak voor de temperatuur.
Ik koos voor

pic basic code:

TempB = BME280_Read(0xFA)

Blijft echter waarde 128 geven.

Dat zou temp MSB moeten opleveren. Maar er zijn ook temp_xlsb en temp_lsb :?

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Het ding reageert niet op het commando 0xF4. Wat ik ook aan parameters invul. 0xFA (temp MSB) geeft 128 en 0xFB (temp LSB) geeft 0.

Bij 0xD0 zou hij de chip ID (60) moeten geven, maar hij geeft 96...

Het lijkt of hij geen temperatuur meet (of helemaal niet actief is)

De Arduino werkt wel, dus het chipje werkt wel.

Ik heb de arduino codes even bekeken, maar ik kan daar weinig uithalen (waarom het daar wel werkt).

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Wat ik superlastig vind in het Arduino gebeuren (of ik doe iets niet goed :/ ) is het bekijken van de 'libraries' in een Arduino project.
Het hoofdprogramma roept allerlei modules aan en gebruikt variabelen die in de libraries zoals .h en .cpp bestanden staan. Daar gebeurt dus het 'echte' werk.
Maar die dingen staan ergens diep verstopt op de PC. En eenmaal gevonden rest de gang met Notepad o.i.d. om er in te kijken.

Is er geen methode waarbij je het programma in zijn geheel kunt zien (m.a.w. dat de 'includes' worden geëxpandeerd?

Anders ben ik het overzicht helemaal kwijt.

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Het lastige om te vergelijken is het al bestaande probleem van adressering.

De chip heeft als I2C adres 1110110 gevolgd door een 0 voor schrijven.
Wordt dan 0xEC.

Maar in Arduino sketches gebruikt men steeds als adres 0x76 (ze stoppen er een "voorloop" 0 voor).

Ik gebruik de adressen die in de datasheet staan.

Maar nog geen temperatuur. steeds de waarde 128...
0XF4 voor de configuratie heeft ook geen enkel effect.

Alleen 0xD0 geeft een waarde terug. Dat zou de chip ID moeten zijn. Ik krijg de waarde 96 terug (sheet zegt 60).

Wat ik in de tabel ook niet goed begrijp is of er na de reset 0xE0 nog een waarde moet worden weggeschreven (0x00) of juist niet (m.a.w alleen 0xEO).

Dan komt er bij: de waarde die je terug krijgt heb ik als Byte staan. Misschien is dat wel niet juist

pic basic code:

'====================================================================================================
Sub Function BME280_Read(Dim preg as Byte) as Byte
'====================================================================================================
  While Not (i2c1_Is_Idle) wend
  i2c1_Start()                                                      'Start
  I2C1_wr(%11101100)
  i2c1_Wr(pReg)
  i2c1_Repeated_Start()                                             'Bus restart
  I2C1_wr(%11101101)
  Result = i2c1_rd(0)
  I2C1_Stop()
End Sub
Fouten zijn het bewijs dat je het probeert..
paaltje73

Golden Member

Alleen 0xD0 geeft een waarde terug. Dat zou de chip ID moeten zijn. Ik krijg de waarde 96 terug (sheet zegt 60).

96 dec = 60 hex !!!

Bavelt

Golden Member

Zie volgende post

[Bericht gewijzigd door Bavelt op vrijdag 10 april 2020 00:52:05 (96%)

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Ik ben verder!

Het staat eigenlijk ook gewoon in de datasheet:

Als je de (over)sampling niet opgeeft, is de output 0x80!

De temperatuur wordt opgegeven in drie bytes, waarvan er 20 bits worden gebruikt (0xFA, 0xFB, 0xFC).
Samen vormen ze de temperatuur, die nog moet worden 'omgerekend' om het toonbaar te maken.

[Bericht gewijzigd door Bavelt op vrijdag 10 april 2020 00:54:33 (42%)

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Het uitrekenen van de temperatuur is veel lastiger dan gedacht.
In de sheet wordt een stukje code daarvoor gegeven, maar is tamelijk ingewikkeld.

c code:

// Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23
DegC.
// t_fine carries fine temperature as global value
BME280_S32_t t_fine;
BME280_S32_t BME280_compensate_T_int32(BME280_S32_t adc_T)
{
BME280_S32_t var1, var2, T;
var1 = ((((adc_T>>3) &#8211; ((BME280_S32_t)dig_T1<<1))) * ((BME280_S32_t)dig_T2)) >> 11;
var2 = (((((adc_T>>4) &#8211; ((BME280_S32_t)dig_T1)) * ((adc_T>>4) &#8211; ((BME280_S32_t)dig_T1)))
>> 12) *
((BME280_S32_t)dig_T3)) >> 14;
t_fine = var1 + var2;
T = (t_fine * 5 + 128) >> 8;
return T;
}

Geen idee hoe ik dit moet omzetten naar MikroBasic.

De temperatuur kan uit 3 registers worden gehaald, een MSB, een LSB en een XLsb. Samen vormen ze een 20 bits eenheid.

Maar hoe ik dit 'vertaal' naar een begrijpelijke formule weet ik niet.

Wie kan me hierbij helpen?

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Overzichtelijk, he, die C code... ;)
(ik heb recent nog bijna 20.000 regels headercode moeten omzetten uit C... :( )

Er is trouwens wel wat 'lost in translation'. Wat moeten die &# 8211;'s zijn? [edit:] schijnt '-' teken te zijn

Ik denk dat de temperatuur zoiets wordt:

pic basic code:

TempRaw = (regFA << 12) Or (regFB << 4) Or (regFC >> 4)  'TempRaw Dword/Longword

Handig, dat geworstel met bits en nibbles om een paar bytes geheugen op de chip uit te sparen... :(

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

ja, ik vind het een heel geworstel om gewoon een temperatuur uit te lezen.
Dan is die MCP9801 wel een héél stuk makkelijker.

En dat C is voor mij nog steeds een gebrij. Het Arduino gaat bij mij nooit landen vrees ik. Ik heb sketches bekeken, maar ben het overzicht binnen no time kwijt (als ik het daar al had).
MikroBasic is wat dat betreft mijns inziens veel beter, gestructureerder en wat ik helemaal belangrijk vind - Als je een dergelijk programma ziet is het nog te lezen en begrijpen wat er gebeurt...

Ik heb wel eens horen zeggen over C: "Write Once, read never" of zoiets.
Maar er zullen ongetwijfeld anderen zijn die het daar niet mee eens zullen zijn.
Maar enfin.

Ik was in mijn speurtocht en lessen bij de BME280 gekomen. En wilde gewoon zien dat ik het aan de praat kreeg. Dat lukt ook nog, zij het dat wat worstelen wordt om een fatsoenljk getal te presenteren.

Ik begrijp overigens dat de SHT-serie (SHT 21, 30, etc) ook veel wordt gebruikt voor temperatuurmeting. Zijn die dingen vriendelijker in gebruik of moet daar ook worden 'getoverd?'

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Die SHT,s zijn wel wat handiger. (ik vind het voor testen ook een voordeel dat 'ie simpel soldeerbaar is)
C kan heel overzichtelijk zijn, maar het nodigt uit tot het schrijven van onleesbare code. (waar velen dankbaar gebruik van maken... ;) )
(ik vind code goed als je zonder commentaar erbij na een tijdje nog steeds begrijpt wat de code doet...)

Soms maken ze het wel heel bont. De headers die ik moest vertalen zaten vol met dit soort idiote constantes benamingen:

c code:

   IPEC_Q931Cause70OnlyRestrictedDigitalInformationBearerCapabilityIsAvailable = 3070, /* 0xbfe*/

(Constantes zijn er normaal om alles eenvoudiger te maken, maar op deze manier lukt dat niet erg... ;) )

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

TempRaw = (regFA << 12) Or (regFB << 4) Or (regFC >> 4) 'TempRaw Dword/Longword

(RegFA is een byte, hoe kan die dan 12 bits naar links opschuiven?)

Ik krijg het volgende resultaat op de display:

MSB (0xFA) = 131
LSB (0xFB) = 35
Xlsb (0xFC) = 112

Het eindresultaat: TempRaw = 12979

Zit hier een logica in (Die ik niet zie? :> )

En wat is nu de uiteindelijke temperatuur?

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Je kunt de registers voor de berekening opslaan in een dword voor de zekerheid.
Iets gaat er mis: de berekening zou als uitkomst 537143 moeten hebben. (heb je wel een Longword gebruikt en geen Word?)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Er zat idd iets fout: bij de omzetting van de waarde naar de string: ik had daar IntToStr ipv zoals nu LongWordtoStr.

Nu komt er uit
131- 27 - 240 wordt totaal 537023

Komt dus in de buurt.... :)

Maar hoe vertaal ik deze grote waarde nu naar de echte temperatuur?

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Die waarde klopt inderdaad... ;)
Maar wat je er precies mee moet zie ik ook niet zo gauw. Het schijnt van heel veel ingestelde parameters af te hangen.
(oversampling, filtering, compensation,...)

Ik begrijp er weinig van. Ze raden waarschijnlijk niet voor niets aan om altijd hun eigen API te gebruiken... ;)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Ik ook niet. Diverse posts bekeken, maar krijg nergens een goede formule hoe de juiste temperatuur nu te tonen.
De Arduino sketch (werkt overigens wel) is voor mij niet te doorgronden.

Ik denk dat ik deze BME280 proef maar afsluit; deze gaat hem niet worden. Veel te ingewikkeld gedoe.

Volgende oefening maar...

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Ik heb het projectje afgesloten door er een constante in te bouwen die de Raw-temperatuur omrekent, ervan uitgaande dat het verloop lineair is.

Hij loopt aardig synchroon met de MCP9801, die in hetzelfde programma wordt aangestuurd.

In ieder geval heb ik het projectje als bijlage bij deze post gezet.
Heel misschien heeft iemand er ooit wat aan.

Fouten zijn het bewijs dat je het probeert..