MCP3208 i mikropyton na RPi Pico

Jakiś czas temu pytałem tutaj o środowisko typu SBC, na którym mógłbym sobie coś zmajstrować konkretnego i pouczyć pytona. Wtedy wspominałem o kolorymetrii, ale wyszło cos pilniejszego i obecnie próbuję ogarnąć obsługę MCP3208 pod ww. RPi (potrzebuje 8-mio kanałowy odczyt tenperatury). Tzn. zasadniczo mam z lekka ją ogarnietą, ale dla MCP3008. To zasadniczo wygląda tak, że biblioteka do MCP3008 obsługuje bez żadnych modyfikacji MCP3208, no ale dostaję wynik 10bit. Czy jakaś dobra dusza mogłaby mi trochę powyjasniać, bo tu nie tylko że pyton ale jeszcze programowanie cipa dochodzi? Pytania w kodzie.

Poniżej kod dla mcp3008.py stąd:

formatting link
import machine

class MCP3008:

def __init__(self, spi, cs, ref_voltage=3.3): """ Create MCP3008 instance

Args: spi: configured SPI bus cs: pin to use for chip select ref_voltage: r """ self.cs = cs self.cs.value(1) # ncs on self._spi = spi self._out_buf = bytearray(3) self._out_buf[0] = 0x01 self._in_buf = bytearray(3) self._ref_voltage = ref_voltage

# co robią te bufory in and out? Rozumiem, że pierwszy bajt coś ustawia, # a dwa pozostałe są na dane?

def reference_voltage(self) -> float: """Returns the MCP3xxx's reference voltage as a float.""" return self._ref_voltage

def read(self, pin, is_differential=False): """ read a voltage or voltage difference using the MCP3008.

Args: pin: the pin to use is_differential: if true, return the potential difference between two pins,

Returns: voltage in range [0, 1023] where 1023 = VREF (3V3)

"""

self.cs.value(0) # select self._out_buf[1] = ((not is_differential) << 7) | (pin << 4) self._spi.write_readinto(self._out_buf, self._in_buf)

#kopiuje zawartość out do in?

self.cs.value(1) # turn off return ((self._in_buf[1] & 0x03) << 8) | self._in_buf[2]

#tu widzę jakieś przesuwania bitów, ale jak wielkość bufora jest bajt to #przesunięcie o 8 co daje? A co daje binarne "and" zawartości [1] z #00000011? Dostaję 2 młodsze bity, które w połączeniu z [2] dają 10 #bitów? Jeśli tak to 0x0F powinno z tego zrobić 12bit a jakby nie rozbi #- jak podłącze na odpowiedni pin MC3208 3V3 to nadal dostaje 1023, więc #ta bitowość może jest gdzies definiowana w "machine"?

Reply to
Marcin Debowski
Loading thread data ...

Marcin Debowski snipped-for-privacy@INVALID.zoho.com> napisał(a):

Bufory transmitowane po SPI, jeden na dane do wysłania drugi na dane odbierane. W nadawczym ustawiana jest wartość pierwszego bajtu. Pierwszy transmitowany bajt zawiera bit startu i bity kontrolne, które wybierają kanał oraz określają czy odczyt ma być bezwzględny czy różnicowy. Rozdział 5 w datasheecie.

Wysyła zawartość out po SPI, odebrane dane umieszcza w in.

Co Cię obchodzi bufor? To nie w nim jest przesunięcie. Odczytywana jest wartość spod indeksu 1 do tymczasowego miejsca w pamięci i tam jest przesunięcie. To tymczasowe miejsce zapewne jest co najmniej 16-bitowe. Bufor nie jest modyfikowany.

Zerowanie starszych 6 bitów, a zachowanie 2 młodszych bez zmian.

Co to jest machine?

MCP3208 zaczyna wysyłać dane nie w określonym miejscu od początku transmisji SPI, jak to zwykle bywa, ale od momentu bitu startu. Ten bit nie musi być pierwszym bitem w transmisji. Stąd wychodzi, że to gdzie będą bity danych jest trochę płynne i zależy od Ciebie. Zobacz sobie obrazek 6-1. Najpierw przez 5 cykli (bitów) lecą zera, potem bit startu, bit trybu, trzy bity adresu. Następnie przez 1 bit/cykl nic się nie dzieje. Dopiero potem lecą dane. Ponieważ bit startu był w tym miejscu w jakim był, dane zaczynają się od połowy drugiego bajtu.

Zobacz co się dzieje w tym kodzie. self._out_buf[0] = 0x01 Bit startu jest umieszczony na końcu pierwszego bajtu. Czyli po rozpoczęciu transmisji leci 7 zer i potem jedynka. self._out_buf[1] = ((not is_differential) << 7) | (pin << 4) Bity kontrolne. Na najstarszym miejscu, czyli zaraz po bicie startu, jest bit trybu. Potem bity kanału.

Czyli wysyłane jest:

0000000S TKKK0000

Układ odpowiada po dwóch cyklach (jeden pusty i jeden zerowy). Czyli co mamy?

0000000S TKKK0000 00000000 0000P0DD

Czyli w drugim bajcie masz dwa pierwsze bity odpowiedzi. Są to bity 11 i 10. Co się stało jak poszerzyłeś maskę o dwa bity w lewo? Odczytałeś pusty bit i zerowy. Cały problem polega na tym, że nie masz czytać wcześniej, ale później. Masz wziąć dwa bity z bajtu 1, osiem z bajtu 2 oraz DODATKOWO 2 bity z bajtu 3. Tylko, że aktualnie nie masz bajtu o indeksie 3, bo transmitujesz tylko 3 bajty (indeksy 0 - 2). Musisz wydłużyć transmisję.

Albo zrobić inaczej: wcześniej wysłać bajt startu: self._out_buf[0] = 0x04 #start self._out_buf[1] = ((not is_differential) << 1 | (pin >> 2) self._out_buf[2] = pin << 6 I wtedy odczyt: return ((self._in_buf[1] & 0x0f) << 8) | self._in_buf[2]

Ogólnie zamieszanie wynika ze stosowania bitu startu, który jest charakterystyczny dla portu szeregowego. W tym układzie to on wyznacza początek transmisji a nie opadający /CS. Choć /CS i tak musi najpierw opaść. Obrazki dobrze to pokazują.

I nie trzeba unikać datasheetu. Lektura karty katalogowej nie gryzie, a pozwala zaoszczędzić czasu i nerwów.

Reply to
Grzegorz Niemirowski

Wielkie dzięki. Muszę to na spokojnie przetrawic i poeksperymentować. I to nie tak, że unikam datasheetu ale rozmawiasz z osobą, która nigdy w czymś takim (programowanie ptzrtworników i podobnych) nie robiła, więc trochę za duża dziura w wiedzy.

Reply to
Marcin Debowski

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.