I2C und Datenübergabe

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
Caraboules
User
Beiträge: 5
Registriert: Montag 17. Februar 2020, 17:28

Hallo Zusammen,

nachdem ich jetzt zwei Tage lang das Internet einmal von rechts auf links gekrempelt habe, hoffe ich, dass Ihr mir helfen könnt:

Ich habe eine Verbindung vom RaspberryPi zu einem Arduino.
Über diese Verbindung möchte ich nun verschiedene Werte übertragen.
Dies funktioniert auch.
Allerdings soll ein Wert "1000" betragen,
Diesen Wert bekomme ich aber nicht übertragen.
Meine Frage:

Wie bekomme ich den Wert "1000" in Bytes zerlegt (also Darstellung in Form von "255" er Blöcken).
Ich bin blutiger Anfänger und lege mir gerade die Karten.

Vielen Dank für Eure Hilfe.
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dazu ist zb das struct-Modul geeignet. Damit kann man Python-Werte in kompakte Byte-Darstellungen uebertragen, die fuer I2C geeignet sind.

Code: Alles auswählen

import struct
print(struct.pack("<H", 1000))
Ob little endian (<) und ein unsigned short (also zwei Bytes, kein Vorzeichen) jetzt fuer dich passen musst du wissen. Es findet sich in der Dokumentation eine Uebersicht darueber, was da so alles geht.
Caraboules
User
Beiträge: 5
Registriert: Montag 17. Februar 2020, 17:28

Hallo __deets__

danke für die Antwort. Leider funktioniert das nicht. Ich bekomme immer folgende Ausgabe:
"TypeError: Third argument must be a list of at least one, but not more than 32 integers"
(Das dritte Argument ist die Zahl > 255)
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

Vielleicht solltest du dann mal zeigen, was du tust? Es kann ja nicht sein, was __deets__ dir gezeigt hat, denn da gibt es kein 3. Argument.
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Zeig doch mal bitte was du machst, denn bei mir funktioniert das sehr wohl.
Caraboules
User
Beiträge: 5
Registriert: Montag 17. Februar 2020, 17:28

Hier ist der Code:

Code: Alles auswählen

#!/usr/bin/env python3
####### NeoPixel LED-ring  #######
###### Import Modules ######
import time, sys
import signal, os, subprocess
import smbus
import struct

###### Initialization ######
#### Initialize I2C-Bus
bus                 = smbus.SMBus(1)
address             = 0x04
#times               = int
#seconds             = int

#### Initialize colors for NeoPixel
black               = [0,0,0]
white               = [255,255,255]
green               = [0,255,0]
yellow              = [255,100,0]
red                 = [255,0,0]
blue                = [0,0,255]
pink                = [255,20,147]
purple              = [125,38,205]

#### Initialize modes for LED-ring
static              = 1
blinking            = 2
clockwise           = 3
counterclockwise    = 4

#### I2C-Bus operations
def write_Data(value1,value2,value3,value4,value5,value6,value7):
    byteValue = [value1,value2,value3,value4,value5]
    byteValue += value6
    byteValue += value7
    # Busaddress, Offset, Data
    bus.write_i2c_block_data(address,0,byteValue) #first byte is 0=command byte.. just is.
    return -1

def led_ring(mode, times, seconds, brightness_1, brightness_2, color_1, color_2=black):
    seconds_new = struct.pack("<H",seconds)
    write_Data(mode,times,seconds_new,brightness_1,brightness_2,color_1,color_2)
    print(seconds)

#### Example
# Syntax: led_ring(mode, times, seconds, brightness 1st color, brightness 2nd color, 1st color, 2nd color)
led_ring(blinking,5,1000,100,10,purple)
Und hier die Ausgabe:

Traceback (most recent call last):
File "./led_neu.py", line 50, in <module>
led_ring(blinking,5,1000,100,10,purple)
File "./led_neu.py", line 45, in led_ring
write_Data(mode,times,seconds,brightness_1,brightness_2,color_1,color_2)
File "./led_neu.py", line 40, in write_Data
bus.write_i2c_block_data(address,0,byteValue) #first byte is 0=command byte.. just is.
TypeError: Third argument must be a list of at least one, but not more than 32 integers

Ich hatte zuerst die Daten wie o.a. eingetragen, das hat leider auch nicht funktioniert :-(
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

write_i2c_block_data will eine Liste von Bytes. Und du uebergibst jetzt zwischendurch einen Bytes-STRING, das ist ein Objekt mit mehrerer Bytes gleich drin. Ein Weg das zu machen waere, *ALLE* Parameter die in das I2C-Datagramm muessen per struct zu formatieren, und dann einfach eine Liste aus dem Ergebnis zu machen:

Code: Alles auswählen

data = struct.pack("<BBHBBBB", mode, times, seconds_new, brightness_1, brightness_2, color_1, color_2)
bus.write_i2c_block_data(address, 0, list(data))
Es ist uebrigens eine ganz doofe Angewohnheit, Namen einfach nur durchzunummerieren. Dann nimmt man gleich eine Liste. Und warum du byteValue erst als Liste erzeugst, aber dann statt einfach value6 und value7 (was auch immer die sind...) extra anhaengst, anstatt die gleich in die Liste aufzunehmen, erschliesst sich mir auch nicht.
Caraboules
User
Beiträge: 5
Registriert: Montag 17. Februar 2020, 17:28

Ich bin, wie bereits geschrieben, blutiger Anfänger, weshalb mein Programm manchmal etwas komisch erscheint.

Was value6 und value7 angeht: die Variablen color_1 und color_2 geben Ihrerseits den RGB-Farbcode zurück. Wenn ich diese Values direkt in Liste packe, übernimmt er die Daten nicht. "Addiere" ich sie allerdings zur Liste, dann klappt es. Aber das ist ein anderes Thema.

Ich habe jetzt die von Dir erstellte Zeile kopiert. Auf dem I2C-Bus wird jetzt alles als "-1" übertragen...
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ah, ok, dann ist das extend. Das habe ich uebersehen.

Deine Fehlermeldung ist allerdings wieder ziemlich wertlos. 'Geht nicht' ist nicht wirklich etwas, zu dem man fundiert was sagen kann. Bitte zeig den konkreten Code, wie die Daten die gesandt werden aussehen, und welche Fehlermeldungen es gibt.

Und was ggf. hilft: erstmal von Hand ein Beispiel bauen, von dem du weisst, dass es geht. Und dessen Gestalt dann mit dem vergleichen, was durch den Code erzeugt wird.
Caraboules
User
Beiträge: 5
Registriert: Montag 17. Februar 2020, 17:28

Ich habe hier nochmal den modifizierten Quellcode:

Code: Alles auswählen

#!/usr/bin/env python3
###### Import Modules ######
import time, sys
import signal, os, subprocess
import smbus
import struct

###### Initialization ######
#### Initialize I2C-Bus
bus                 = smbus.SMBus(1)
address             = 0x04

#### Initialize colors for NeoPixel
black               = [0,0,0]
white               = [255,255,255]
green               = [0,255,0]
yellow              = [255,100,0]
red                 = [255,0,0]
blue                = [0,0,255]
pink                = [255,20,147]
purple              = [125,38,205]

#### Initialize modes for LED-ring
static              = 1
blinking            = 2
clockwise           = 3
counterclockwise    = 4

#### I2C-Bus operations
def led_ring(mode, times, seconds, brightness_1, brightness_2, color_1, color_2=black):
        data = struct.pack("<BBHBBBB", mode, times, seconds, brightness_1, brightness_2, color_1, color_2)
        bus.write_i2c_block_data(address, 0, list(data))

#### Example
# Syntax: led_ring(mode, times, seconds, brightness 1st color, brightness 2nd color, 1st color, 2nd color)
led_ring(blinking,5,1000,100,10,purple,black)
Und hier die Fehlermeldung:
Traceback (most recent call last):
File "./led_neu.py", line 36, in <module>
led_ring(blinking,5,1000,100,10,purple,black)
File "./led_neu.py", line 31, in led_ring
data = struct.pack("<BBHBBBB", mode, times, seconds, brightness_1, brightness_2, color_1, color_2)
struct.error: required argument is not an integer
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist ja nun eine andere Fehlermeldung als gerade behauptet . Und auch nicht verwunderlich nachdem was du mir dann erzaehlt hast - du musst natuerlich die Farben explizit enkodieren, also statt einem B fuer eine Farbe muessen es drei sein (BBB), und dann muessen color_1[0], color_1[1], color_1[2] uebergeben werden.

Code: Alles auswählen

data = struct.pack("<BBHBBBBBBBB", mode, times, seconds, brightness_1, brightness_2, color_1[0], ..., color_2[0], ...)
ACHTUNG, ich habe keine Lust gehabt das 6-mal hinzuschreiben, das ist Hausaufgaben! Und die Dokumentation von struct durchlesen, damit du solchen Fehlern selbst auf die Spur kommst.
Antworten