I2C v Pythonu a práce s bity

Karlitos

I2C v Pythonu a práce s bity
« kdy: 20. 12. 2014, 22:27:37 »
Dobry den,

hraju si ted se sbernici i2c v Pythonu a mam urcite trable s porozumenim fungovani.

Mam real-time clock i2c modul pripojeny k Raspbery Pi. Komunikace mi funguje, pouzivam modul smbus.

Kód: [Vybrat]
import smbus

bus = smbus.SMBus(0)
# 0x83 zapina 1Hz frekvenci na pinu CLK OUT
bus.write_byte_data(0x51, 0x0D, 0x83)
# nacti obsah registru 0x01 do returndata
returndata = bus.read_byte_data(0x51, 0x01)

Ty data jsou v registrech ulozena ve formatu BCD, takze se musi prepocitat abych dostal decimalni reprezentaci.

Kde mam ale problem s porozumenim je, jak zjistim treba obsah 3.bitu v registru XYZ. A jak ho zmenim. Nasel jsem si jedno [url?http://tronixstuff.com/2013/08/13/tutorial-arduino-and-pcf8563-real-time-clock-ic/]how-to[/url] k tomuto modulu, to je ale pro Arduino.

Citace
Checking if the alarm has occurred can be done with two methods – software and hardware. Using software you check bit 3 of the register at 0x01 (the “AF” alarm flag bit). If it’s 1 – it’s alarm time! Then you can turn the alarm off by setting that bit to zero. Using hardware, first set bit 1 of register 0x01 to 1 – then whenever an alarm occurs, current can flow into pin 3 of the PCF8563.

Za nejake vysvetleni bych byl moc vdecny.
« Poslední změna: 22. 12. 2014, 08:07:07 od Petr Krčmář »


Re:i2c v Pythonu (smbus) - jak cist/menit jednotlive bity v registrech
« Odpověď #1 kdy: 20. 12. 2014, 22:41:00 »
Kde mam ale problem s porozumenim je, jak zjistim treba obsah 3.bitu v registru XYZ.
Nactes cely registr a 3. bit si z něj vylovíš pomocí bitové masky.

A jak ho zmenim.
Načteš původní hodnotu z registru, opět pomocí masky změníš 3. bit a výsledek zapíšeš zpátky.

Karlitos

Re:i2c v Pythonu (smbus) - jak cist/menit jednotlive bity v registrech
« Odpověď #2 kdy: 20. 12. 2014, 22:59:28 »
Bitova maska - prolit sem clanek ve Wikipedii, chapu dobry.

Co ale porad nechapu je, jak aplikuju tu bitovou masku v Pythonu. Podle toho co jsem videl v cizich kodech, kdyz jsem hledal jak funguje i2c/smbus v Pythonu tak tam casto bylo treba neco jako value & 0x11. Chapu to tedy dobre ze si tu bitovou masku musim prelozit do hexadecimalni tvaru ? A co dostanu, zase nejakou hodnotu ... a co s ni ? Kdyz hledam hodnotu jednoho konkretniho bitu staci kdyz kontroluji jestli je je hodnota po aplikaci bitove masky ruzna od nuly ?

Jenda

Re:i2c v Pythonu (smbus) - jak cist/menit jednotlive bity v registrech
« Odpověď #3 kdy: 20. 12. 2014, 23:33:00 »
Chapu to tedy dobre ze si tu bitovou masku musim prelozit do hexadecimalni tvaru ?
Není to nutné, ale když ten kód po tobě bude číst někdo trochu pokročilejší, velmi to ocení. Z hexadecimálního tvaru je na první pohled vidět, co to dělá, z desítkového si to alespoň já musím přepočítat.

A co dostanu, zase nejakou hodnotu ... a co s ni ? Kdyz hledam hodnotu jednoho konkretniho bitu staci kdyz kontroluji jestli je je hodnota po aplikaci bitove masky ruzna od nuly ?
Pak ještě použiješ bitshift. Nebo uděláš bitshift před tím, pak je to ještě čitelnější. Příklad: hodnota 3. bitu je (číslo >> 3) & 1.

Karlitos

Re:i2c v Pythonu (smbus) - jak cist/menit jednotlive bity v registrech
« Odpověď #4 kdy: 20. 12. 2014, 23:55:46 »
Ok, takze podle toho navodu ziskam hodnotu "AF" the alarm bit flag
Kód: [Vybrat]
>>> import smbus
>>>
>>> bus = smbus.SMBus(0)
>>> returndata = bus.read_byte_data(0x51, 0x01)
>>> returndata
114
>>> (returndata >> 3) & 1
0

Takze ted jeste zjistit jak nastavit ten alarm a pak to muzu zkusit.

Citace
Using hardware, first set bit 1 of register 0x01 to 1

Se tedy provede:

Kód: [Vybrat]
>>> newdata = (returndata | 1)
>>> newdata
115
>>> bus.write_byte_data(0x51, 0x0D, newdata)


Karlitos

Re:i2c v Pythonu (smbus) - jak cist/menit jednotlive bity v registrech
« Odpověď #5 kdy: 20. 12. 2014, 23:57:18 »
Ech... asi chyba ne ?

Je tohle spravne ?
Kód: [Vybrat]
newdata = ((returndata >> 1 ) | 1)
>>> newdata
57
>>> bus.write_byte_data(0x51, 0x0D, newdata)

Re:i2c v Pythonu (smbus) - jak cist/menit jednotlive bity v registrech
« Odpověď #6 kdy: 21. 12. 2014, 00:36:20 »
Je tohle spravne ?
Kód: [Vybrat]
newdata = ((returndata >> 1 ) | 1)
>>> newdata
57
>>> bus.write_byte_data(0x51, 0x0D, newdata)
Ne. Při nastavování bitu nesmíš provádět bitshift.

Hele, nejlepší  je, když si to číslo převedeš do binárního tvaru, tam to uvidíš jasně:

http://www.binaryconvert.com/result_unsigned_char.html?decimal=049049053

- v čísle 115 už ten 1. bit je nastavený. Představ si, že máš dvě čísla pod sebou (to původní číslo + maska) a provádíš OR -> tou maskou tam přidáš bit na místo, kde případně původně nebyl.

Např.
1011 OR 0100 -> 1111
Kdybys provedl bitshift, ztratíš ty spodní bity:

1011 >> 1 -> 0101 OR 0100 -> NESMYSL

Re:i2c v Pythonu (smbus) - jak cist/menit jednotlive bity v registrech
« Odpověď #7 kdy: 21. 12. 2014, 00:43:36 »
- v čísle 115 už ten 1. bit je nastavený.
Jo soráč, teď jsem se přehlídl - v registru bylo číslo 114, pak jsi nastavil NULTÝ bit a tím jsi dostal číslo 115.

Na to si dej taky bacha, jestli ten manuál, ze kterýho to čteš, čísluje bity od nuly (to je myslím častější) nebo od jedničky.

Nastavení nultého bitu: (x | 1)
Nastavení prvního: (x | 2) neboli (x | (1 << 2))

Karlitos

Re:i2c v Pythonu (smbus) - jak cist/menit jednotlive bity v registrech
« Odpověď #8 kdy: 21. 12. 2014, 09:40:59 »
Diky vam vsem za odpovedi.

Jelikoz jsem zelenac tak si na http://www.binaryhexconverter.com/ vzdycky zjistim danou hex hodnotu te masky a s tou pak pracuji. Nakonec z toho vcera vecer vyplybul nejaky kod pro ten real-timce clock, tak to ted budu testovat Tak uvidim jestli to bude fungovat.

Re:i2c v Pythonu (smbus) - jak cist/menit jednotlive bity v registrech
« Odpověď #9 kdy: 21. 12. 2014, 10:07:58 »
Super :) Kdyžtak ještě pak napiš, jestli ti to i funguje, ať máme plnou satisfakci ;)

Karlitos

Re:i2c v Pythonu (smbus) - jak cist/menit jednotlive bity v registrech
« Odpověď #10 kdy: 21. 12. 2014, 17:22:24 »
Tak aby byla satisfakce uplna doplnil jsem ty veci, ktere se mi zatim podarilo implementovat do puvodni knihovny na GitHubu Poslal jsem autorovi pull request, predchozi mi prijmul, tak uvidime  ;)

Jinak nakonec jsem skoncil u lusteni datasheetu, protoze v tom navodu pro Arduino je chyba:

Citace
However there is a catch – the MSB (most significant bit, 7) in the registers above is used to determine whether that particular register plays a part in the alarm. For example, if you want your alarm to include hours and minutes, bit 7 needs to be set to 1 for the hour and minute alarm register.

No a datasheet nam rika:

Citace
By clearing the alarm enable bit (AE_x) of one or more of the alarm registers, the
corresponding alarm condition(s) are active.

Trochu nelogicky je:

1 - tento casovy udaj NEhraje roli
0 - tento casovy udaj HRAJE roli

Kdyz jsem to udelal podle datasheetu tak mi ten alarm fungoval. Tak o tom asi i pisnu tomu manikovi co delal ten navod pro to Arduino - takhle plist lidi   :P :P :P

Diky moc za vysvetleni a navedeni spravnym smerem !

Re:i2c v Pythonu (smbus) - jak cist/menit jednotlive bity v registrech
« Odpověď #11 kdy: 21. 12. 2014, 18:58:40 »
Super. Happy hacking! :)