Отправлять числа в arduino через последовательный порт с помощью python
У меня есть файл с номерами под названием fginputs.txt
. Например, это может быть что-то вроде этого:
4958
4154
4154
4154
4154
4154
4154
4154
4154
4154
4154
4154
4154
4154
4154
4154
4154
4958
Я хочу, чтобы Python отправлял каждое число в Arduino через последовательный порт. После получения каждого числа arduino должна распечатать номер подтверждения, указывающий, что он получил действительное число, а затем сохранить это число в динамическом массиве, потому что я мог бы создавать файлы большего размера. Когда номеров больше не останется, отправьте «-1», чтобы завершить передачу.
Вот мой код Arduino:
// сохранить несколько целых чисел без знака
uint16_t SIZE, *inputList, cont = 0;
boolean inputsReady = false;
void setup()
{
// инициализируем последовательную связь со скоростью 9600 бит в секунду:
Serial.begin(9600);
//свободная память динамического массива
free(inputList);
//счетчик полученных чисел начинается с 0
cont = 0;
//Это правда, когда больше нет чисел для приема, в то время как ложь
inputsReady = false;
setupInputList();
}
/* If there's not enough space, resize the array by one unit and store the number
*/
void growAndInsert(int currentSize, int newInt){
if(currentSize > SIZE)
inputList = (uint16_t *)realloc(inputList, (currentSize + 1)*sizeof(uint16_t));
inputList[currentSize] = newInt;
}
/**
init inputList with 100 blocks
*/
void setupInputList(){
SIZE = 10;
inputList = (uint16_t *)malloc(sizeof(uint16_t) * SIZE);
}
void clearBuffer(){
while(Serial.available() > 0)
Serial.read();
}
/**
Listens in serial port for an integer that represents a new input and returns it.
If it doesn't get anything useful from serial, return 0
*/
int getNewInputFromSerial(){
if (Serial.available() > 0) {
delay(100);
// ищем следующее слово
int cmd = Serial.parseInt();
clearBuffer();
if(cmd == 4958)
Serial.write("4");
else if(cmd == 4154)
Serial.write("5");
else
Serial.write("0");
return cmd;
}
return 0;
}
void loop()
{
if(!inputsReady){
int newInput = getNewInputFromSerial();
if(newInput == 0)
return;
if(newInput != -1)
growAndInsert(cont++, newInput);
else{
inputsReady = true;
//иниттаймер();
}
}
}
и скрипт Python:
global arduino
PORT = '/dev/ttyACM0'
FILENAME = "fginputs.txt"
#Read file with inputs
with open(FILENAME) as f:
content = f.readlines()
#init serial port
arduino = serial.Serial(PORT, 9600, timeout=1);
time.sleep(2);
#write
for input in content:
arduino.flush()
arduino.write(input)
time.sleep(.1);
resp = arduino.read();
print "i got " + resp
#Finish transmission with -1
arduino.flush()
arduino.write("-1")
#done
arduino.close();
При первом запуске скрипта я получаю следующее:
i got 4
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 4
Это здорово. Но если я запущу его во второй раз, я получу следующее:
i got 0
i got 4
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
Что ужасно неправильно, потому что файл не изменился. Я не знаю, что здесь происходит. Если я отключу и снова подключу USB-кабель, передача снова будет работать безупречно.
@Diego, 👍0
2 ответа
Лучший ответ:
// сохранить несколько целых чисел без знака
uint16_t SIZE, *inputList, cont = 0;
boolean inputsReady = false;
void setup()
{
// инициализируем последовательную связь со скоростью 9600 бит в секунду:
Serial.begin(9600);
//свободная память динамического массива
free(inputList);
Вы освобождаете указатель NULL, который является неопределенной операцией и здесь не нужен, так как он никогда не выделялся.
if (Serial.available() > 0) {
delay(100);
// ищем следующее слово
int cmd = Serial.parseInt();
clearBuffer();
Это приведет к потере данных, я не удивлен, что что-то пропало.
Прочитайте это: Как обрабатывать входящие последовательные данные без блокировки — вам нужно избавиться от задержки
и clearBuffer()
для начала.
Пример кода для чтения из Serial без блокировки и без использования delay
:
// сколько последовательных данных мы ожидаем перед новой строкой
const unsigned int MAX_INPUT = 50;
void setup ()
{
Serial.begin (115200);
} // конец настройки
// здесь для обработки входящих последовательных данных после получения терминатора
void process_data (const char * data)
{
// пока просто отображаем его
// (но вы можете сравнить его с каким-то значением, преобразовать в целое число и т. д.)
Serial.println (data);
} // конец process_data
void processIncomingByte (const byte inByte)
{
static char input_line [MAX_INPUT];
static unsigned int input_pos = 0;
switch (inByte)
{
case '\n': // конец текста
input_line [input_pos] = 0; // завершающий нулевой байт
// терминатор достигнут! обработать input_line здесь...
process_data (input_line);
// сброс буфера для следующего раза
input_pos = 0;
break;
case '\r': // отменить возврат каретки
break;
default:
// продолжаем добавлять, если не полный ... разрешить завершающий нулевой байт
if (input_pos < (MAX_INPUT - 1))
input_line [input_pos++] = inByte;
break;
} // конец переключателя
} // конец процессаIncomingByte
void loop()
{
// если серийные данные доступны, обрабатываем их
while (Serial.available () > 0)
processIncomingByte (Serial.read ());
// делаем здесь другие вещи, например, тестируем цифровой ввод (нажатие кнопок) ...
} // конец цикла
В моем примере в process_data
вы должны вызвать atoi
для преобразования входящей строки в int (или atol
, если она собирается быть длиннее).
Вы можете посмотреть это.
Это программа на Python, которая записывает/воспроизводит нажатия клавиш через UNO.
Он уже реализует:
- последовательная связь с проверкой ошибок
- ACK: каждое сообщение имеет собственный идентификатор, поэтому вы можете отслеживать, что было потеряно, если что-то случится.
- синхронизация, если питание Arduino включается после запуска программы python
- Программирование серийного описания
- Не удается связаться с ардуино с помощью python (Windows)
- Максимальная последовательная скорость CH340
- Последовательная связь Arduino с Python: отправка массива
- Построение графика на Python с использованием Tkinter Canvas
- Можно ли загрузить скетч Arduino через последовательный порт (RX) вместо USB?
- Как отправить целое число через pyserial с Python на Arduino и получить тот же результат?
- Может ли Arduino Leonardo одновременно использовать USB-порт и последовательные контакты RX TX?
бесплатно(NULL)
можно; per man malloc revoid free(void *ptr)
, «Если ptr равен NULL, никакая операция не выполняется»., @James Waldby - jwpat7Ах, ты прав. Тем не менее, бессмысленная вещь в
настройке
. Сообщение исправлено., @Nick Gammon