RTV forum PL | NewsGroups PL

MCP3208 i mikropyton na RPi Pico

NOWY TEMAT

elektroda NewsGroups Forum Index - Elektronika Polska - MCP3208 i mikropyton na RPi Pico

Marcin Debowski
Guest

Wed Jul 05, 2023 6:54 am   



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:
https://blog.rareschool.com/2021/02/raspberry-pi-pico-project-2-mcp3008.html

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) << Cool | 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"?

--
Marcin

Grzegorz Niemirowski
Guest

Wed Jul 05, 2023 12:58 pm   



Marcin Debowski <agatek@INVALID.zoho.com> napisał(a):
Quote:
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?

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.

Quote:
self._spi.write_readinto(self._out_buf, self._in_buf)
#kopiuje zawartość out do in?

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

Quote:
return ((self._in_buf[1] & 0x03) << Cool | self._in_buf[2]
#tu widzę jakieś przesuwania bitów, ale jak wielkość bufora jest bajt to
#przesunięcie o 8 co daje?

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.

Quote:
A co daje binarne "and" zawartości [1] z
#00000011?

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

Quote:
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"?

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) << Cool | 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.

--
Grzegorz Niemirowski
https://www.grzegorz.net/

Marcin Debowski
Guest

Thu Jul 06, 2023 5:34 am   



On 2023-07-05, Grzegorz Niemirowski <grzegorz@grzegorz.net> wrote:
Quote:
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) << Cool | 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.

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.

--
Marcin

elektroda NewsGroups Forum Index - Elektronika Polska - MCP3208 i mikropyton na RPi Pico

NOWY TEMAT

Regulamin - Zasady uzytkowania Polityka prywatnosci Kontakt RTV map News map