В настоящее время я работаю с отличным исходным кодом hackboard-firmware-hack на GitHub, и это действительно здорово. В настоящее время я работаю с протоколом UART, поэтому могу общаться с материнской платой на ховерборде через последовательный UART. Хост милостиво предоставил пример кода Arduino для отправки базовой команды с использованием пользовательского протокола прошивки:
SoftwareSerial mySerial(10, 11); // RX, TX
typedef struct MsgToHoverboard_t{
unsigned char SOM; // 0x02
unsigned char len; // len is len of ALL bytes to follow, including CS
unsigned char cmd; // 'W'
unsigned char code; // code of value to write
int16_t base_pwm; // absolute value ranging from -1000 to 1000 .. base_pwm plus/minus steer is the raw PWM value
int16_t steer; // absolute value ranging from -1000 to 1000 .. wether steer is added or substracted depends on the side R/L
unsigned char CS; // checksumm
};
uint16_t baseSpeed = 0;
typedef union UART_Packet_t{
MsgToHoverboard_t msgToHover;
byte UART_Packet[sizeof(MsgToHoverboard_t)];
};
void setHoverboardPWM( int16_t base_pwm, int16_t steer )
{
UART_Packet_t ups;
ups.msgToHover.SOM = 2 ; // PROTOCOL_SOM; //Start of Message;
ups.msgToHover.len = 7; // payload + SC only
ups.msgToHover.cmd = 'W'; // PROTOCOL_CMD_WRITEVAL; // Write value
ups.msgToHover.code = 0x07; // speed data from params array
ups.msgToHover.base_pwm = base_pwm;
ups.msgToHover.steer = steer;
ups.msgToHover.CS = 0;
for (int i = 0; i < ups.msgToHover.len; i++){
ups.msgToHover.CS -= ups.UART_Packet[i+1];
}
mySerial.write(ups.UART_Packet,sizeof(UART_Packet_t));
}
Это отлично работает! В настоящее время я пытаюсь сделать это на RPi и не захожу слишком далеко, потому что Python может сбить с толку тем, что он не очень строго типизирован, а размеры байтов могут быть затруднены.
Я попробовал свои силы в C ++, используя termios, но не захожу слишком далеко. Функция выглядит так:
//Hover couch Serial test
#include <cstdint>
#include <iostream>
#include <stdio.h>
#include <unistd.h> //Used for UART
#include <fcntl.h> //Used for UART
#include <termios.h> //Used for UART
using namespace std;
typedef struct MsgToHoverboard_t
{
unsigned char SOM; // 0x02
unsigned char len; // len is len of ALL bytes to follow, including CS
unsigned char cmd; // 'W'
unsigned char code; // code of value to write
int16_t base_pwm; // absolute value ranging from -1000 to 1000 .. base_pwm plus/minus steer is the raw PWM value
int16_t steer; // absolute value ranging from -1000 to 1000 .. wether steer is added or substracted depends on the side R/L
unsigned char CS; // checksumm
} MsgToHoverboard_t;
uint16_t baseSpeed = 0;
typedef union UART_Packet_t {
MsgToHoverboard_t msgToHover;
uint8_t UART_Packet[sizeof(MsgToHoverboard_t)];
} UART_Packet_t;
void setHoverboardPWM(int16_t base_pwm, int16_t steer, int &handle)
{
UART_Packet_t ups;
ups.msgToHover.SOM = 2; // PROTOCOL_SOM; //Start of Message;
ups.msgToHover.len = 7; // payload + SC only
ups.msgToHover.cmd = 'W'; // PROTOCOL_CMD_WRITEVAL; // Write value
ups.msgToHover.code = 0x07; // speed data from params array
ups.msgToHover.base_pwm = base_pwm;
ups.msgToHover.steer = steer;
ups.msgToHover.CS = 0;
for (int i = 0; i < ups.msgToHover.len; i++)
{
ups.msgToHover.CS -= ups.UART_Packet[i + 1];
}
// mySerial.write(ups.UART_Packet,sizeof(UART_Packet_t));
if (handle != -1)
{
int count = write(handle, &ups.UART_Packet, sizeof(UART_Packet_t)); //Filestream, bytes to write, number of bytes to write
// cout << "count: " << count << endl;
if (count < 0)
{
printf("UART TX error\n");
}
}
}
int main()
{
//-------------------------
//----- SETUP USART 0 -----
//-------------------------
//At bootup, pins 8 and 10 are already set to UART0_TXD, UART0_RXD (ie the alt0 function) respectively
int uart0_filestream = -1;
//OPEN THE UART
//The flags (defined in fcntl.h):
// Access modes (use 1 of these):
// O_RDONLY - Open for reading only.
// O_RDWR - Open for reading and writing.
// O_WRONLY - Open for writing only.
//
// O_NDELAY / O_NONBLOCK (same function) - Enables nonblocking mode. When set read requests on the file can return immediately with a failure status
// if there is no input immediately available (instead of blocking). Likewise, write requests can also return
// immediately with a failure status if the output can't be written immediately.
//
// O_NOCTTY - When set and path identifies a terminal device, open() shall not cause the terminal device to become the controlling terminal for the process.
uart0_filestream = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY); //Open in non blocking read/write mode
if (uart0_filestream == -1)
{
//ERROR - CAN'T OPEN SERIAL PORT
printf("Error - Unable to open UART. Ensure it is not in use by another application\n");
}
//CONFIGURE THE UART
//The flags (defined in /usr/include/termios.h - see http://pubs.opengroup.org/onlinepubs/007908799/xsh/termios.h.html):
// Baud rate:- B1200, B2400, B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800, B500000, B576000, B921600, B1000000, B1152000, B1500000, B2000000, B2500000, B3000000, B3500000, B4000000
// CSIZE:- CS5, CS6, CS7, CS8
// CLOCAL - Ignore modem status lines
// CREAD - Enable receiver
// IGNPAR = Ignore characters with parity errors
// ICRNL - Map CR to NL on input (Use for ASCII comms where you want to auto correct end of line characters - don't use for bianry comms!)
// PARENB - Parity enable
// PARODD - Odd parity (else even)
struct termios options;
tcgetattr(uart0_filestream, &options);
options.c_cflag = B19200 | CS8 | CLOCAL | CREAD; //<Set baud rate
options.c_iflag = IGNPAR;
options.c_oflag = 0;
options.c_lflag = 0;
tcflush(uart0_filestream, TCIFLUSH);
tcsetattr(uart0_filestream, TCSANOW, &options);
cout << "Beginning serial output\n";
while (1)
{
setHoverboardPWM(200, 0, uart0_filestream);
}
//----- CLOSE THE UART -----
close(uart0_filestream);
return 0;
}
Это в значительной степени заимствованный код. Я старался изо всех сил, чтобы заставить его работать. Тем не менее, я получаю тонну «UART TX error!» (Изнутри SetHoverBoard PWM). Я не очень опытен с протоколами связи UART, но я знаю, что моя скорость передачи данных верна, а последовательный порт работает. Я просто делаю упаковку неправильно?
Может ли кто-нибудь, имеющий опыт работы с этим материалом, помочь мне либо воспроизвести этот код на python, либо исправить мой текущий код на c ++?
Я также предоставлю пример кода TX, с которым я работал, на случай, если я только что испортил это:
ссылка на код: https://raspberry -projects.com / pi / program-in-c / uart-serial-port / using-the-uart
Сам код:
//----- TX BYTES -----
unsigned char tx_buffer[20];
unsigned char *p_tx_buffer;
p_tx_buffer = &tx_buffer[0];
*p_tx_buffer++ = 'H';
*p_tx_buffer++ = 'e';
*p_tx_buffer++ = 'l';
*p_tx_buffer++ = 'l';
*p_tx_buffer++ = 'o';
if (uart0_filestream != -1)
{
int count = write(uart0_filestream, &tx_buffer[0], (p_tx_buffer - &tx_buffer[0])); //Filestream, bytes to write, number of bytes to write
if (count < 0)
{
printf("UART TX error\n");
}
}
Я предполагаю битовый паритет, и все в порядке. Кажется, настройки совпадают.