spi_documentation_2
Différences
Ci-dessous, les différences entre deux révisions de la page.
| Prochaine révision | Révision précédente | ||
| spi_documentation_2 [2022/05/30 13:10] – créée serge | spi_documentation_2 [2022/05/31 07:45] (Version actuelle) – serge | ||
|---|---|---|---|
| Ligne 1: | Ligne 1: | ||
| ====== Communication entre Raspberry Pi et Arduino en SPI ====== | ====== Communication entre Raspberry Pi et Arduino en SPI ====== | ||
| + | <WRAP center round box 60% centeralign> | ||
| + | **{{tagpage> | ||
| + | </ | ||
| - | {{tag>sb spi communication}} | + | =====Une ESP32 n'est pas une carte Arduino===== |
| + | **Les sketchs ci-dessous ne fonctionnent pas avec une ESP32** | ||
| + | |||
| + | =====Exemple 1===== | ||
| + | https:// | ||
| + | |||
| + | Raspberry Pi (master) Arduino Uno (slave) SPI communication with WiringPi | ||
| + | |||
| + | <code csharp> | ||
| + | #include < | ||
| + | void setup() { | ||
| + | // have to send on master in, *slave out* | ||
| + | pinMode(MISO, | ||
| + | // turn on SPI in slave mode | ||
| + | SPCR |= _BV(SPE); | ||
| + | // turn on interrupts | ||
| + | SPI.attachInterrupt(); | ||
| + | } | ||
| + | // SPI interrupt routine | ||
| + | ISR (SPI_STC_vect) | ||
| + | { | ||
| + | byte c = SPDR; | ||
| + | SPDR = c+10; | ||
| + | } // end of interrupt service routine (ISR) for SPI | ||
| + | |||
| + | void loop () { } | ||
| + | </ | ||
| + | |||
| + | **Raspberry Pi avec wiringPi** | ||
| + | < | ||
| + | #include < | ||
| + | #include < | ||
| + | #define SPI_CHANNEL 0 | ||
| + | #define SPI_CLOCK_SPEED 1000000 | ||
| + | int main(int argc, char **argv) | ||
| + | { | ||
| + | int fd = wiringPiSPISetupMode(SPI_CHANNEL, | ||
| + | if (fd == -1) { | ||
| + | std::cout << " | ||
| + | return -1; | ||
| + | } | ||
| + | std::cout << "SPI communication successfully setup.\n"; | ||
| + | |||
| + | unsigned char buf[2] = { 23, 0 }; | ||
| + | wiringPiSPIDataRW(SPI_CHANNEL, | ||
| + | std::cout << "Data returned: " << +buf[1] << " | ||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | Voir le lien pour la compilation de wiringPi et de ce script | ||
| + | |||
| + | =====Exemple 2===== | ||
| + | Tiré de [[http:// | ||
| + | Arduino: SPCR et SPDR pas défini ! | ||
| + | ====Raspberry==== | ||
| + | <code python> | ||
| + | import spidev | ||
| + | import time | ||
| + | spi_bus = 0 | ||
| + | spi_device = 0 | ||
| + | spi = spidev.SpiDev() | ||
| + | spi.open(spi_bus, | ||
| + | spi.max_speed_hz = 1000000 | ||
| + | # Send a null byte to check for value | ||
| + | send_byte = 0x80 | ||
| + | rcv_byte = spi.xfer2([send_byte]) | ||
| + | # repeat to check for a response | ||
| + | rcv_byte = spi.xfer2([send_byte]) | ||
| + | data_recv = rcv_byte[0] | ||
| + | if (data_recv != 0x80): | ||
| + | print (" | ||
| + | quit() | ||
| + | # Data is sent as single bytearray | ||
| + | # lower 4 bits = pin number | ||
| + | # returns a value that is used to set a digital pin | ||
| + | # pin = Arduino pin number | ||
| + | # state = True for high, False for low | ||
| + | # returns byte or 0xff = invalid | ||
| + | def req_set_digital (pin, state): | ||
| + | if (pin < 0 or pin > 10): | ||
| + | return 0xff | ||
| + | if (state == True): | ||
| + | pin += 0x60 | ||
| + | else : | ||
| + | pin += 0x20 | ||
| + | return pin | ||
| + | # read analog pin | ||
| + | def req_read_analog (pin): | ||
| + | if (pin < 0 or pin > 5): | ||
| + | return 0xff | ||
| + | return pin + 0x10 | ||
| + | # read digital pin | ||
| + | def req_read_digital (pin): | ||
| + | if (pin < 0 or pin > 10): | ||
| + | return 0xff | ||
| + | return pin | ||
| + | while True: | ||
| + | # Turn LEDs on | ||
| + | for i in range (3, 10) : | ||
| + | send_byte = req_set_digital (i, True) | ||
| + | rcv_byte = spi.xfer2([send_byte]) | ||
| + | time.sleep (0.5) | ||
| + | # Turn back off again | ||
| + | for i in range (3, 10) : | ||
| + | send_byte = req_set_digital (i, False) | ||
| + | rcv_byte = spi.xfer2([send_byte]) | ||
| + | time.sleep (0.5) | ||
| + | # Get status of pin 2 | ||
| + | send_byte = req_read_digital(2) | ||
| + | rcv_byte = spi.xfer2([send_byte]) | ||
| + | # Delay to allow Arduino to get answer ready | ||
| + | time.sleep (0.25) | ||
| + | # Send null request | ||
| + | send_byte = 0xf0 | ||
| + | rcv_byte = spi.xfer2([send_byte]) | ||
| + | print (" | ||
| + | |||
| + | # Get status of analog 0 | ||
| + | send_byte = req_read_analog(0) | ||
| + | rcv_byte = spi.xfer2([send_byte]) | ||
| + | # Delay to allow Arduino to get answer ready | ||
| + | time.sleep (0.25) | ||
| + | # Send null request | ||
| + | send_byte = 0xf0 | ||
| + | rcv_byte = spi.xfer2([send_byte]) | ||
| + | print (" | ||
| + | </ | ||
| + | |||
| + | ====Arduino==== | ||
| + | <code csharp> | ||
| + | #include < | ||
| + | // track if digital pins are set as input or output (saves reading registers) | ||
| + | // Pins 0 to 9 can be used, pin 10 can be used for SS (but can be used if that's not required) | ||
| + | bool pin_output[11]; | ||
| + | void setup() | ||
| + | { | ||
| + | // by default all pins are inputs | ||
| + | for (int i=0; i<11; i++) | ||
| + | { | ||
| + | pin_output[i] = false; | ||
| + | } | ||
| + | // Set the Main in Secondary Out as an output | ||
| + | pinMode(MISO, | ||
| + | // turn on SPI as a secondary | ||
| + | // Set appropriate bit in SPI Control Register | ||
| + | SPCR |= _BV(SPE); | ||
| + | } | ||
| + | void loop () | ||
| + | { char print_text [50]; | ||
| + | byte in_byte; | ||
| + | // SPIF indicates transmission complete (byte received) | ||
| + | if ((SPSR & (1 << SPIF)) != 0) | ||
| + | { | ||
| + | in_byte = SPDR; | ||
| + | // if no action bit sent then return same | ||
| + | if (in_byte & 0x80) SPDR = in_byte; | ||
| + | // if write set | ||
| + | else if (in_byte & 0x20) | ||
| + | { | ||
| + | // set digital pin output - use mask to extract pin and output | ||
| + | if (set_digital_pin (in_byte & 0x0F, in_byte & 0x40) != 0xFF) SPDR = in_byte; | ||
| + | } | ||
| + | // If value is only pin numbers then digital read | ||
| + | else if (in_byte < 0x10) | ||
| + | { | ||
| + | byte return_val = read_digital_pin (in_byte); | ||
| + | SPDR = return_val; | ||
| + | } | ||
| + | else if ((in_byte & 0x10) && !(in_byte & 0x20)) | ||
| + | { | ||
| + | byte return_val = read_analog_pin (in_byte & 0x0F); | ||
| + | SPDR = return_val; | ||
| + | } | ||
| + | else // Otherwise an error - return 0xff | ||
| + | { | ||
| + | SPDR = 0xFF; | ||
| + | }}} | ||
| + | |||
| + | byte set_digital_pin (byte address, bool high_value) | ||
| + | { | ||
| + | if (address < 0 || address > 10) return 0xFF; | ||
| + | // Is it currently set as output - if not then set to output | ||
| + | if (!pin_output[address]) | ||
| + | { | ||
| + | pinMode(address, | ||
| + | pin_output[address] = true; | ||
| + | } | ||
| + | // set to low if 0, otherwise 1 | ||
| + | if (high_value == 0) digitalWrite(address, | ||
| + | else digitalWrite (address, HIGH); | ||
| + | } | ||
| + | |||
| + | // Returns 1 for high and 0 for low | ||
| + | // If invalid then returns 0xff | ||
| + | byte read_digital_pin (byte address) | ||
| + | { | ||
| + | if (address < 0 || address > 10) return 0xFF; | ||
| + | // if currently output then change to input | ||
| + | if (pin_output[address]) | ||
| + | { | ||
| + | pinMode(address, | ||
| + | pin_output[address] = false; | ||
| + | } | ||
| + | return digitalRead (address); | ||
| + | } | ||
| + | // As full byte is used for value there is no invalid value | ||
| + | // If invalid then returns 0x00 | ||
| + | byte read_analog_pin (byte address) | ||
| + | { | ||
| + | if (address < 0 || address > 5) return 0x00; | ||
| + | int analog_val = analogRead (address); | ||
| + | // Analog value is between 0 and 1024 - div by 4 for byte | ||
| + | return (analog_val / 4); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | {{tag> | ||
spi_documentation_2.1653916242.txt.gz · Dernière modification : de serge
