Forum » Programiranje » [RPi, C, SPI] razlaga kode za nooba
[RPi, C, SPI] razlaga kode za nooba

wajdouc ::
Zdravo.
Imam RPi 4B, 6 senzorjev BMI088 (SPI), pigpio.h knjižnica, program je v C.
Z SPI se pri programiranju prvič srečujem, do sedaj imam nekaj malega izkušenj z I2C in programiral sem večinoma na Arduino, kjer zaradi že spisanih knjižnic nisem imel kakšnih večjih težav pri osnovnem razumevanju delovanja kode. Sedaj že nekaj dni buljim v kodo in vsak dan manj razumem, kaj gledam.
Na RPi bi rad preko SPI povezave bral podatke iz vseh 6 senzorjev. Knjižnica pigpio.h omogoča bit banging in na strani http://abyz.me.uk/rpi/pigpio/examples.h... je podan tudi primer za branje podatkov iz več ADC-jev MCP3202. Problem je, ker kode v večini ne razumem in bi prosil nekoga, da bi mi pomagal pri razumevanju.
Druga stvar je, da se preko SPI ne morem povezati niti z enim senzorjem, ki je priključen na SPI0 na RPi. Glede na dokumentacijo knjižnice sem spisal naslednjo kodo (vse spremenljivke so deklarirane, prevede se brez napak. Če tole prilagodim za I2C, deluje BP):
Tole pa dobim ven, kar ni v redu:
Kaj mi manjka? Kaj sem spregledal?
Imam RPi 4B, 6 senzorjev BMI088 (SPI), pigpio.h knjižnica, program je v C.
Z SPI se pri programiranju prvič srečujem, do sedaj imam nekaj malega izkušenj z I2C in programiral sem večinoma na Arduino, kjer zaradi že spisanih knjižnic nisem imel kakšnih večjih težav pri osnovnem razumevanju delovanja kode. Sedaj že nekaj dni buljim v kodo in vsak dan manj razumem, kaj gledam.
Na RPi bi rad preko SPI povezave bral podatke iz vseh 6 senzorjev. Knjižnica pigpio.h omogoča bit banging in na strani http://abyz.me.uk/rpi/pigpio/examples.h... je podan tudi primer za branje podatkov iz več ADC-jev MCP3202. Problem je, ker kode v večini ne razumem in bi prosil nekoga, da bi mi pomagal pri razumevanju.
Druga stvar je, da se preko SPI ne morem povezati niti z enim senzorjem, ki je priključen na SPI0 na RPi. Glede na dokumentacijo knjižnice sem spisal naslednjo kodo (vse spremenljivke so deklarirane, prevede se brez napak. Če tole prilagodim za I2C, deluje BP):
int main(int argc, char *argv[]) { gpio_initialization(); delayms(100); int h, x1, x2, y1, y2, z1, z2; spiOpen(0, 32000, 0); h = spiOpen(0, 32000, 0); if(h <= 0) { printf("SPI error!\n"); } else { printf("SPI open! %d\n", h); } delayms(100); buffer[0] = 0x41; buffer[1] = 0x03; spiWrite(h, (char*)buffer, 2); delayms(10); buffer[0] = 0x40; buffer[1] = 0xAC; spiWrite(h, (char*)buffer, 2); delayms(10); buffer[0] = 0x7C; buffer[1] = 0x00; spiWrite(h, (char*)buffer, 2); delayms(10); buffer[0] = 0x7D; buffer[1] = 0x04; spiWrite(h, (char*)buffer, 2); delayms(10); buffer[0] = 0x12; buffer[1] = 0x13; buffer[2] = 0x14; buffer[3] = 0x15; buffer[4] = 0x16; buffer[5] = 0x17; spiWrite(h, (char*)buffer, 6); delays(1); for(i = 0; i < 1000; i++) { spiRead(h, (char*)buffer, 6); x1 = buffer[0]; x2 = buffer[1]; y1 = buffer[2]; y2 = buffer[3]; z1 = buffer[4]; z2 = buffer[5]; printf("X:%d %d\tY:%d %d\tZ:%d %d\n", x1, x2, y1, y2, z1, z2); delayms(100); } spiClose(h); gpioSetMode(record_data_led, PI_OUTPUT); // LED output pin gpioSetMode(record_switch_pin, PI_INPUT); // Data recording switch input pin while(1) { start_data_switch(); } }
Tole pa dobim ven, kar ni v redu:
GPIO initialisation successful SPI open! 1 X:0 0 Y:0 0 Z:0 0 X:0 0 Y:0 0 Z:0 0 X:0 0 Y:0 0 Z:0 0 X:0 0 Y:0 0 Z:0 0 X:0 0 Y:0 0 Z:0 0 X:0 0 Y:0 0 Z:0 0 X:0 0 Y:0 0 Z:0 0
Kaj mi manjka? Kaj sem spregledal?

slawc ::
Imaš možnost pogledati kaj se dogaja na pinih kjer je SPI? Osciloskop mogoče?
Lahko predvidevamo, da je povezano vse kot mora biti: izbira SPI načina, pravi pini na RPi, pravi chip select signali (senzor ima kar dva), kaj pa LSB/MSB bit poslanega byta?
Lahko predvidevamo, da je povezano vse kot mora biti: izbira SPI načina, pravi pini na RPi, pravi chip select signali (senzor ima kar dva), kaj pa LSB/MSB bit poslanega byta?
LP,
Slawc

Ahim ::

wajdouc ::
@slawc
Na RPi so pravi pini (19, 21, 23, 24), povezano je tako, kot piše v datasheet, stran 42 (CSB2 in INT1 do INT4 ne potrebujem).
Osciloskop lahko dobim. Če povežem MISO in MOSI med sabo dobim, kar pošljem na senzor.
Poizkusil sem tudi povezati na Arduino in stvar dela, kot mora.
@Ahim
Typo, nima vpliva na delovanje kode, ker ne dela v obeh primerih.
Na RPi so pravi pini (19, 21, 23, 24), povezano je tako, kot piše v datasheet, stran 42 (CSB2 in INT1 do INT4 ne potrebujem).
Osciloskop lahko dobim. Če povežem MISO in MOSI med sabo dobim, kar pošljem na senzor.
Poizkusil sem tudi povezati na Arduino in stvar dela, kot mora.
@Ahim
Typo, nima vpliva na delovanje kode, ker ne dela v obeh primerih.

wajdouc ::

slawc ::
Na strani 42 datasheet-a imam jaz opis registrov. datasheet
Glede na tvoj loopback test (thumbs up) in posnetek MISO je videti, da čip ne ve, da je izbran oz. da ne ve, da mora komunicirati po SPI.
Kako imaš pa zvezan pin PS?
Glede na tvoj loopback test (thumbs up) in posnetek MISO je videti, da čip ne ve, da je izbran oz. da ne ve, da mora komunicirati po SPI.
Kako imaš pa zvezan pin PS?
LP,
Slawc

slawc ::
Ja, se mi je zdelo, da bo ta. Meni je res videti, da te čip ne posluša/zastopi. Vseeno preveri kaj se dogaja s CS signalom in initom pri komunikaciji s SPI (3. poglavje).
in pa prvo vrstico spiInit zbriši in pusti tisto s h = spiInit. Vseeno ni ok, da kličeš 2x, čudi me, da sploh dela (handle bi moral biti zaseden in 2x klic bi moral vrniti negativno vrednost)
Čip sam po sebi pa očitno dela (če ti uspe dobiti podatke iz njega preko spi s pomočjo arduino platforme).
in pa prvo vrstico spiInit zbriši in pusti tisto s h = spiInit. Vseeno ni ok, da kličeš 2x, čudi me, da sploh dela (handle bi moral biti zaseden in 2x klic bi moral vrniti negativno vrednost)
Čip sam po sebi pa očitno dela (če ti uspe dobiti podatke iz njega preko spi s pomočjo arduino platforme).
LP,
Slawc

slawc ::
Poleg tega imaš preverjanje napačno:
Če bom našel čas in kakšen rpi pri roki, bom poskusil spisati nek del primera in posneti z osciloskopom tudi sam, kljub temu, da nimam tega čipa. Vseeno me zanima kaj točno dela ta library (jaz sem spisal svoj kernel driver)
Returns a handle (>=0) if OK, otherwise PI_BAD_SPI_CHANNEL, PI_BAD_SPI_SPEED, PI_BAD_FLAGS, PI_NO_AUX_SPI, or PI_SPI_OPEN_FAILED.
Če bom našel čas in kakšen rpi pri roki, bom poskusil spisati nek del primera in posneti z osciloskopom tudi sam, kljub temu, da nimam tega čipa. Vseeno me zanima kaj točno dela ta library (jaz sem spisal svoj kernel driver)
LP,
Slawc
Zgodovina sprememb…
- spremenil: slawc ()

wajdouc ::
Trenutno uporabljam drugo knjižnico (bcm2835), mi bolj odgovarja glede na moj nivo znanja.
Sumim tudi to, da z RPi ne inicializiram pravilno senzorja. Bom pogledal, kako je Arduino knjižnica spisana za ta senzor, če mi bo kaj pomagalo.
Sumim tudi to, da z RPi ne inicializiram pravilno senzorja. Bom pogledal, kako je Arduino knjižnica spisana za ta senzor, če mi bo kaj pomagalo.

slawc ::
Zelo verjetno je res tako. Danes sem preizkusil ta lib, firbec pač. Primer kode spodaj.
Rezultat:
Ker sem pozabil narediti povezavo MOSI in MISO sem v rx_buf prejel same 0, posledično je printf brez izpisa. Žal nimam tega senzorja, da bi preizkusil delovanje.
Da vidim kateri driver uporablja zadnji raspbian: lsmod | grep spi
spidev 20480 0
spi_bcm2835 20480 0
CS se postavi na '1' kmalu po priklopu napajanja. Zelo verjetno senzor ne dobi prave informacije, da naj preklopi v SPI način (pulz CS iz '0' na '1' po POR sekvenci senzorja). To bi lahko preveril, če bi brez power downa in reseta še vedno lahko komuniciral preko I2C.
Kasneje sem preizkusil še dvakrat klicati funkcijo spiOpen. Vsak klic vzame nov handle. Prvi open vrne 0, naslednji 1. In če ga ne zapreš, bo ostal prvi zaseden. Dela še vedno, vendar ni prav, vprašanje kaj se zgodi s tem, ko se program zaključi. Verjetno visi nekje, zganja dolgčas, ker handle ni sproščen.
int main(int argc, char *argv[]) { int32_t h; uint8_t tx_buf[] = { 't', 'e', 's', 't'}; uint8_t rx_buf[] = { 'e', 'm', 'p', 't', 'y', 0}; if (gpioInitialise() < 0) { printf("\nError with gipio init\n"); return 1; } h = spiOpen(0, 32000, 0); printf("\nHandle = %d\n",h); if (h < 0) { printf("\nError with handle\n"); return 2; } printf("\nString before xfer: %s\n",rx_buf); spiXfer(h, tx_buf, rx_buf, 4); printf("\nString after xfer: %s\n", rx_buf); spiClose(h); gpioTerminate(); return 0; }
Rezultat:
Ker sem pozabil narediti povezavo MOSI in MISO sem v rx_buf prejel same 0, posledično je printf brez izpisa. Žal nimam tega senzorja, da bi preizkusil delovanje.
Da vidim kateri driver uporablja zadnji raspbian: lsmod | grep spi
spidev 20480 0
spi_bcm2835 20480 0
CS se postavi na '1' kmalu po priklopu napajanja. Zelo verjetno senzor ne dobi prave informacije, da naj preklopi v SPI način (pulz CS iz '0' na '1' po POR sekvenci senzorja). To bi lahko preveril, če bi brez power downa in reseta še vedno lahko komuniciral preko I2C.
Kasneje sem preizkusil še dvakrat klicati funkcijo spiOpen. Vsak klic vzame nov handle. Prvi open vrne 0, naslednji 1. In če ga ne zapreš, bo ostal prvi zaseden. Dela še vedno, vendar ni prav, vprašanje kaj se zgodi s tem, ko se program zaključi. Verjetno visi nekje, zganja dolgčas, ker handle ni sproščen.
LP,
Slawc
Zgodovina sprememb…
- spremenil: bluefish ()

slawc ::
Beh... koda je adijo pamet, pozabil sem dati "vstavi kodo", popraviti pa ne morem več. Mondays, 4th with me was not.
LP,
Slawc

wajdouc ::
Sem ugotovil, kaj je bilo narobe, da se senzor ni zbudil.
Pri pošiljanju naslovov registrov za branje preko SPI je potrebna še maska 0x80, v nasprotnem primeru se senzor ne odziva.
Uporabil sem knjižnico bmc2835, mi je malo bolj razumljiva kot pigpio.
Pri pošiljanju naslovov registrov za branje preko SPI je potrebna še maska 0x80, v nasprotnem primeru se senzor ne odziva.
Uporabil sem knjižnico bmc2835, mi je malo bolj razumljiva kot pigpio.
Zgodovina sprememb…
- spremenilo: wajdouc ()
Vredno ogleda ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | Arduino in luči (strani: 1 2 )Oddelek: Elektrotehnika in elektronika | 12776 (10402) | FX6300B |
» | C (Izračun povprečja)Oddelek: Programiranje | 1700 (1334) | joze67 |
» | C strukture, kazalci naloga pomocOddelek: Programiranje | 1544 (1439) | DavidJ |
» | C osnovaOddelek: Programiranje | 1622 (1137) | RunoTheDog |
» | [c++]UrejanjepoljaOddelek: Programiranje | 1424 (1245) | purki |