Last active
September 3, 2026 11:47
-
-
Save orjanv/9a2679897da862da2acdd4eb88bfb929 to your computer and use it in GitHub Desktop.
Enkel konfigurator for EBYTE E32-radioer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| E32 Konfigurator | |
| Bruk: | |
| Les konfig: | |
| python e32config.py COM4 read | |
| python e32config.py /dev/ttyUSB0 read | |
| Sett kanal: | |
| python e32config.py COM4 setchan 23 | |
| Sett adresse: | |
| python e32config.py COM4 setaddr 42 | |
| Sett UART baud: | |
| python e32config.py COM4 setbaud 19200 | |
| """ | |
| import sys | |
| import time | |
| import serial | |
| # E32 støttede UART-baudrater | |
| UART_BAUD_CODES = { | |
| 1200: 0, | |
| 2400: 1, | |
| 4800: 2, | |
| 9600: 3, | |
| 19200: 4, | |
| 38400: 5, | |
| 57600: 6, | |
| 115200: 7, | |
| } | |
| CODE_TO_UART_BAUD = {v: k for k, v in UART_BAUD_CODES.items()} | |
| VALID_BAUDS = [ | |
| 1200, | |
| 2400, | |
| 4800, | |
| 9600, | |
| 19200, | |
| 38400, | |
| 57600, | |
| 115200, | |
| ] | |
| AIR_RATE_MAP = { | |
| 0: "0.3 kbps", | |
| 1: "1.2 kbps", | |
| 2: "2.4 kbps", | |
| 3: "4.8 kbps", | |
| 4: "9.6 kbps", | |
| 5: "19.2 kbps", | |
| } | |
| class E32: | |
| def __init__(self, port): | |
| self.port = port | |
| self.baudrate = None | |
| self.ser = None | |
| def connect(self): | |
| """ | |
| Prøv alle lovlige baudrater til radioen svarer. | |
| """ | |
| for baud in VALID_BAUDS: | |
| try: | |
| ser = serial.Serial( | |
| self.port, | |
| baudrate=baud, | |
| timeout=1 | |
| ) | |
| ser.reset_input_buffer() | |
| ser.write(b"\xC1\xC1\xC1") | |
| data = ser.read(6) | |
| if len(data) == 6: | |
| self.ser = ser | |
| self.baudrate = baud | |
| print(f"Fant radio på {baud} baud") | |
| return | |
| ser.close() | |
| except Exception: | |
| pass | |
| raise RuntimeError( | |
| "Fant ingen E32-radio. " | |
| "Sjekk port, M0/M1 og kabling." | |
| ) | |
| def read_config(self): | |
| self.ser.reset_input_buffer() | |
| self.ser.write(b"\xC1\xC1\xC1") | |
| data = self.ser.read(6) | |
| if len(data) != 6: | |
| raise RuntimeError("Ingen respons fra radio.") | |
| return list(data) | |
| def write_config(self, addh, addl, sped, chan, option): | |
| cmd = bytes([ | |
| 0xC0, | |
| addh, | |
| addl, | |
| sped, | |
| chan, | |
| option | |
| ]) | |
| self.ser.write(cmd) | |
| # radioen trenger tid til EEPROM | |
| time.sleep(1) | |
| def decode_config(self, cfg): | |
| head, addh, addl, sped, chan, option = cfg | |
| address = (addh << 8) | addl | |
| # SPED-format | |
| # | |
| # bit7-6 Air rate | |
| # bit5-3 UART baud | |
| # bit2-0 UART parity | |
| uart_code = (sped >> 3) & 0b111 | |
| parity_code = sped & 0b111 | |
| air_rate_code = (sped >> 6) & 0b11 | |
| uart_baud = CODE_TO_UART_BAUD.get( | |
| uart_code, | |
| "ukjent" | |
| ) | |
| air_rate = AIR_RATE_MAP.get( | |
| air_rate_code, | |
| "ukjent" | |
| ) | |
| print() | |
| print("=== E32 Konfigurasjon ===") | |
| print(f"Header : 0x{head:02X}") | |
| print(f"Adresse : {address}") | |
| print(f"ADDH : {addh}") | |
| print(f"ADDL : {addl}") | |
| print(f"UART baud : {uart_baud}") | |
| print(f"Air rate : {air_rate}") | |
| print(f"Parity kode : {parity_code}") | |
| print(f"Kanal : {chan}") | |
| print(f"Frekvens : {433 + chan} MHz") | |
| print(f"SPED : 0x{sped:02X}") | |
| print(f"OPTION : 0x{option:02X}") | |
| print() | |
| def set_channel(self, channel): | |
| cfg = self.read_config() | |
| self.write_config( | |
| cfg[1], | |
| cfg[2], | |
| cfg[3], | |
| channel, | |
| cfg[5] | |
| ) | |
| print(f"Kanal satt til {channel}") | |
| def set_address(self, address): | |
| cfg = self.read_config() | |
| addh = (address >> 8) & 0xFF | |
| addl = address & 0xFF | |
| self.write_config( | |
| addh, | |
| addl, | |
| cfg[3], | |
| cfg[4], | |
| cfg[5] | |
| ) | |
| print(f"Adresse satt til {address}") | |
| def set_uart_baud(self, baud): | |
| if baud not in UART_BAUD_CODES: | |
| raise RuntimeError( | |
| f"Ugyldig baudrate: {baud}" | |
| ) | |
| cfg = self.read_config() | |
| code = UART_BAUD_CODES[baud] | |
| sped = cfg[3] | |
| # nullstill bit 5-3 | |
| sped &= ~(0b111 << 3) | |
| # sett ny baudrate | |
| sped |= (code << 3) | |
| self.write_config( | |
| cfg[1], | |
| cfg[2], | |
| sped, | |
| cfg[4], | |
| cfg[5] | |
| ) | |
| print(f"UART baud satt til {baud}") | |
| def close(self): | |
| if self.ser: | |
| self.ser.close() | |
| def usage(): | |
| print(__doc__) | |
| sys.exit(1) | |
| def main(): | |
| if len(sys.argv) < 3: | |
| usage() | |
| port = sys.argv[1] | |
| command = sys.argv[2] | |
| radio = E32(port) | |
| try: | |
| radio.connect() | |
| if command == "read": | |
| cfg = radio.read_config() | |
| radio.decode_config(cfg) | |
| elif command == "setchan": | |
| if len(sys.argv) != 4: | |
| usage() | |
| channel = int(sys.argv[3]) | |
| if not 0 <= channel <= 31: | |
| raise RuntimeError( | |
| "Kanal må være mellom 0 og 31." | |
| ) | |
| radio.set_channel(channel) | |
| cfg = radio.read_config() | |
| radio.decode_config(cfg) | |
| elif command == "setaddr": | |
| if len(sys.argv) != 4: | |
| usage() | |
| address = int(sys.argv[3]) | |
| if not 0 <= address <= 65535: | |
| raise RuntimeError( | |
| "Adresse må være 0-65535." | |
| ) | |
| radio.set_address(address) | |
| cfg = radio.read_config() | |
| radio.decode_config(cfg) | |
| elif command == "setbaud": | |
| if len(sys.argv) != 4: | |
| usage() | |
| baud = int(sys.argv[3]) | |
| radio.set_uart_baud(baud) | |
| print() | |
| print( | |
| "UART-baudrate er endret." | |
| ) | |
| print( | |
| "Programmet må finne radioen på nytt neste gang." | |
| ) | |
| else: | |
| usage() | |
| finally: | |
| radio.close() | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment