Подача команд по событию в другой программе
- Войдите на сайт для отправки комментариев
Вс, 03/03/2019 - 22:46
Доброго времени суток. Подскажите пожалуйста, в какую сторону копать... Нобходимо запускать скетч (подавать адруине команды) не из ide, а из другой самописной программы. Например: я напишу программу, где есть кнопка "вкл/выкл светодиод" и по нажатию этой кнопки программа подаюет соответствующие команды на ардуину.
Интересует, как это делается, на каком языке нужно писать программу, какие библиотеки используются, а так же примерный код скетча, который будет эти нажатия обрабатывать.
p.s. светодиод подключать я уже научился :)
Программу можно писать на чем угодно - какой вам язык ближе, на том и пишите. Я, к примеру, на Перле писал. Главное, чтобы в языке были средства работы с COM-портом.
Со стороны Ардуины вообще без разницыю что там на большом ПК запускается. Примеров получения данных и Serial в интернете сотни.
Пример кода с обоих сторон (первый попавшийся в гугле)
http://robocraft.ru/blog/1090.html
C#:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO.Ports; namespace WindowsFormsApp2 { public partial class Form1 : Form { public Form1() { InitializeComponent(); // Открываем порт, и задаем скорость в 9600 бод serialPort1.PortName = "COM3"; serialPort1.BaudRate = 9600; serialPort1.Open(); } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { // При закрытии программы, закрываем порт if (serialPort1.IsOpen) serialPort1.Close(); } private void button1_Click(object sender, EventArgs e) { // Передача данных из текстового поля в порт serialPort1.Write(textBox1.Text); // Прием данных и вывод его в окно программмы textBox2.Text = serialPort1.ReadLine(); } } }Arduino:
int val; // Задаем переменную val для отслеживания нажатия клавиши int ledpin = 2; // задаем цифровой интерфейс ввода/вывода - это наш светодиод void setup () { Serial.begin (9600); // Задаем скорость обмена com-порта 9600 pinMode (ledpin, OUTPUT); // Задаем ledpin как интерфейс вывода информации } void loop () { val = Serial.read (); // Считываем команду посланную с компьютера через консоль IDE Arduino if (val == '1') // Задаем букву условие, { digitalWrite (ledpin, HIGH); // Включаем светодиод delay (2000); digitalWrite (ledpin, LOW); // Выключаем светодиод Serial.println ("Hello World!"); // Пишем в консоль "Hello World!" } }Написал на С#. что-то не получается... Хотя через монитор порта в ide всё работает...
Вы удивитесь, но на Ардуино надо писать на си.
Скетч ардуино на С и написан, я говорил про программу на компе... Он на С#...
Все равно вам надо подтянуть свой Си.
const byte ledpin = 2; // задаем цифровой интерфейс ввода/вывода - это наш светодиод void setup (){ Serial.begin (9600); // Задаем скорость обмена com-порта 9600 pinMode (ledpin, OUTPUT); // Задаем ledpin как интерфейс вывода информации } void loop () { if (Serial.available() > 0) { if (Serial.read() == '1') { digitalWrite (ledpin, HIGH); // Включаем светодиод delay (2000); digitalWrite (ledpin, LOW); // Выключаем светодиод Serial.println ("Hello World!"); } } }ПС: Рассматривайте это тестирочным скетчем. Но это совсем не эталон.
В коде ардуино на первый взгляд все нормально. Тем более, раз из монитора все работает - значит проблема в программе на C#
Первый вопрос - ардуина точно к COM3 подключена? - Обычно в винде это порты от COM7 до COM12
Подключите ардуину и запустите одновременно Ардуино ИДЕ и вашу программу. Подставьте в программу тот порт, что определился в Ардуино ИДЕ
Я в С не шарю, но спасибо за оптимизацию кода )) Код из примера взял и он работаел через обычный монитор порта из arduino ide. Видимо, что-то в программе-оболочке на С# не так. Не могу понять что... Ошибок не даёт.
Я через диспетчер устройст смотрел, когда подключал usb, именно 3ий загорается. Но но сейчас попробую ещё раз.
Я через диспетчер устройст смотрел, когда подключал usb, именно 3ий загорается. Но но сейчас попробую ещё раз.
тогда у вас в Ардуино ИДЕ тоже должен быть COM3 ?
В коде ардуино на первый взгляд все нормально. Тем более, раз из монитора все работает - значит проблема в программе на C#
Первый вопрос - ардуина точно к COM3 подключена? - Обычно в винде это порты от COM7 до COM12
Подключите ардуину и запустите одновременно Ардуино ИДЕ и вашу программу. Подставьте в программу тот порт, что определился в Ардуино ИДЕ
Да, 3ий - могу получать оинформацию о плате, загружать скетчи...
Arduino IDE Serial Monitor закрываете, когда своим сишарпом в порт мечете байты?
Arduino IDE Serial Monitor закрываете, когда своим сишарпом в порт мечете байты?
Да. Я быстро понял, что они конфликтуют. Закрываю. Даже ide полностью закрывал.
Arduino IDE Serial Monitor закрываете, когда своим сишарпом в порт мечете байты?
Да. Я быстро понял, что они конфликтуют. Закрываю. Даже ide полностью закрывал.
Кстати, важно. Если открыть программу, а потом попробовать открыть монитор в ide - ругается, что порт занят. Это уже что-то.. А ни чего страшного , что я порт открываю при запуске программы и её закрытии закрываю, соответственно? Не нужно ли перед каждым запросом так делать, что бы он просто так не висел? Глупости, но всё же..
Может какие-то траблы с кодировкой?
Для передачи важно получить доступ к порту. А насколько часто вы его будете открывать-закрывать - разницы нет. Думаю, что тут надо присесть каким-нить программным сниффером на COM, иначе непонятно - шлёт сишарп что-то или не шлёт... Может он вообще в UTF-8 двубайтовые символы шлёт и тогда, понятное дело, что никакой '1' не вылезет из Serial.read(). Что-то там типа маршалинга должно быть перед отсылкой.
Для передачи важно получить доступ к порту. А насколько часто вы его будете открывать-закрывать - разницы нет. Думаю, что тут надо присесть каким-нить программным сниффером на COM, иначе непонятно - шлёт сишарп что-то или не шлёт... Может он вообще в UTF-8 двубайтовые символы шлёт и тогда, понятное дело, что никакой '1' не вылезет из Serial.read(). Что-то там типа маршалинга должно быть перед отсылкой.
Попробовал на ардруине сделать просто "if (Serial.read()) {", что бы он на любое реагировал - чстетно :(
Я на сишарпе не писатель, но попробуйте переменную типа byte слать, потому что char там двубайтовый.
Я на сишарпе не писатель, но попробуйте переменную типа byte слать, потому что char там двубайтовый.
serialPort.Write() принимает значения только типа string...
попробуйте строчку 13 ардуино скетча поменять с if (val == '1') на
if (val)
Начать лучше с ловли (Serial,avialable() > 0)
попробуйте строчку 13 ардуино скетча поменять с if (val == '1') на
if (val)
Так и сделал. У меня сейчас такой листинг:
const byte ledpin = 2; // задаем цифровой интерфейс ввода/вывода - это наш светодиод void setup () { Serial.begin (9600); // Задаем скорость обмена com-порта 9600 pinMode (ledpin, OUTPUT); // Задаем ledpin 13 как интерфейс вывода информации } void loop () { if (Serial.available() > 0) { if (Serial.read()) { digitalWrite (ledpin, HIGH); // Включаем светодиод delay (2000); digitalWrite (ledpin, LOW); // Выключаем светодиод Serial.println ("Hello World!"); } } }Начать лучше с ловли (Serial,avialable() > 0)
Через монитор в ide теперь после первой команды код выполняется циклично - работает. В оболочке-программе всё так же грусно...
Через монитор в ide теперь после первой команды код выполняется циклично - работает. В оболочке-программе всё так же грусно...
значит ваша программа вообще ничего не передает. Этот код должен реагировать на любой байт из Компорта
Да, скорее всего. Однако порт открывается, как ым уже поняли. Значит программа функционирует, но до момента отправки, как бы это глупо не звучало :) Альтернатив записи в интернете не нахожу. Открывают по другому слегка - пробовал - всё так же.
Есть такой пример кода на ардуину:
const char StaPack = '#'; // Признак начала пакета данных const char EndPack = '|'; // Признак окончания пакета данных const uint16_t TimeOut = 500; // Отвалились через это время mls #include <Servo.h> //используем библиотеку для работы с сервоприводом Servo servo; //объявляем переменную servo типа Servo void setup() { Serial.begin(9600); pinMode(13, OUTPUT); servo.attach(10); //сервопривод на порту 10 servo.write(0); } byte hexToByte (String StrControlHex) { //0 : 255 (1 байт) uint8_t HEX16 = 0; // число 16-е из символа uint8_t exp16 = 1; // степень числа 16 uint8_t decBy = 0; // число 10-е расчитанное без знака StrControlHex.remove(0, 2); //отрезаем управляющие символы (2шт) int i = StrControlHex.indexOf('|'); //определяем дилнну строки if (i == -1) return 0; //фигня пришла а не байт if (i > 2) return 0; //фигня пришла а не байт StrControlHex.remove(i, 1); //отрезаем управляющие символы ('|') for (int j = StrControlHex.length() - 1; j >= 0; j--) { HEX16 = StrControlHex.charAt(j); if (HEX16 >= 48 && HEX16 <= 57) HEX16 = map(HEX16, 48, 57, 0, 9); if (HEX16 >= 65 && HEX16 <= 70) HEX16 = map(HEX16, 65, 70, 10, 15); if (HEX16 >= 97 && HEX16 <= 102) HEX16 = map(HEX16, 97, 102, 10, 15); decBy = decBy + HEX16 * exp16; exp16 = exp16 * 16; } return decBy; //возвращаем десятичное число 1 байт без знака } void loop() { clearPack: // переходим сюда если приняли мусор /отвалились по таймауту/ char IncomChar; String StrControl = ""; while (Serial.available() > 0) { // выгребаем все байты которые пришли в буфер Serial IncomChar = Serial.read(); if (IncomChar == StaPack) { // пришел символ начала посылки данных StrControl += IncomChar; // плюсуем пришедший символ к строке unsigned long currentTime = millis(); // записываем текущее время ReceptionPacket: // начало приема пакета if (Serial.available() > 0) { IncomChar = Serial.read(); StrControl += IncomChar; // плюсуем пришедший символ к строке if (IncomChar == EndPack) break; // вываливаемся из цикла выгребания байт если приняли весь пакет } if (millis() - currentTime >= TimeOut) goto clearPack; // отвалились по TimeOut goto ReceptionPacket; // переход в начало приема пакета } } // конец цикла по выгребанию байт if (StrControl != "") { //Serial.println(StrControl); //печатаем принятый пакет отладка switch (StrControl.charAt(1)) { //применяем полученую строку case 'w': digitalWrite(13, 0); break; case 'x': digitalWrite(13, 1); break; case 'A': servo.write(hexToByte(StrControl)); break; } } }Там стерео открывается. Но мне не важен приём, даже запись не работает...
Тема с кодом на с#, как у меня. У человека всё пишется, но не приходил ответ...
http://arduino.ru/forum/programmirovanie/c-i-arduino
kkolorid, вам учится надо.
PS. Чего это тема из сериала "Что нажать на боинге чтоб взлететь?" не в песочнице?
kkolorid, вам учится надо.
PS. Чего это тема из сериала "Что нажать на боинге чтоб взлететь?" не в песочнице?
Вообще-то всё, что можно было сделать - уже сделано. Осталось исправить ошибки. Чему "учиться"? Танцевать с бубном? Я владею программированием и способен самостоятельно диагностировать совой код, хоть я и не специализируюсь на языках семейства С, в этой проблеме явно есть какая-то особенность, о которой не пишут на каждом шагу.
PS. Мое нахождение тут, вроде, "учиться" и называется. Или как Вы себе обучение представляете? Сидеть в 4ех стенах, зубрить учебник моего возраста? Ух, немогу, меня с таких "помошников" аж бомбит. Лишь бы оставить что-нибудь в теме, не читая ветки. Ник свой прям в полном объеме оправдываете... (Сарказм)
Ну вот такое гугля вываливает - там больше настроек для порта делается http://blablacode.ru/programmirovanie/489
С программы-оболочки просто ни чего не проиходит...
Полный лог работы программы с расширенной информацией: (Открыл - нажал отправить - закрыл)
[04/03/2019 23:10:48]
Переписал программу в 5ый раз - заработало... :/ Всем спасибо.
Я владею программированием и способен самостоятельно диагностировать совой код
Ну ладно диагностировать хрустальным шаром. Но шоб совой!
Я владею программированием и способен самостоятельно диагностировать совой код
Ну ладно диагностировать хрустальным шаром. Но шоб совой!
думаю, что это уже граничит с жестоким обращением с животными. вот!