Как писать web-приложения на c++ – arduino+

Практическое программирование Arduino/CraftDuino – общение с Arduino – программирование работы с COM-портом

8. Общение с Arduino — программирование работы с COM-портом.

Правильным местом с которого стоит начать своё изучение написание программ для взаимодействия с Arduino/CraftDuino является официальный сайт:— там приведены примеры работы с последовательным портом из разных языков и сред программирования. Ниже рассмотрим примеры работы с Arduino на С, С++, С#, PERL и Python.

Arduino + C

приводится в пример консольная POSIX C – программа, исходник которой можно скачать

— программа может принимать и передавать данные на плату Arduino/Freeduino

Использование:

laptop% gcc -o arduino-serial arduino-serial.c laptop% ./arduino-serial Usage: arduino-serial -p [OPTIONS] Options: -h, –help Print this help message -p, –port=serialport Serial port Arduino is on -b, –baud=baudrate Baudrate (bps) of Arduino -s, –send=data Send data to Arduino -r, –receive Receive data from Arduino & print it out -n –num=num Send a number as a single byte -d –delay=millis Delay for specified milliseconds
Примечание: Порядок параметров имеет значение! '-b' нужно устанавливать перед указыванием порта '-p'. Можно устанавливать несколько флагов для выполнения последовательности действий: '-d 2000 -s hello -d 100 -r' Означает: «ждать 2 секунды, отправить 'hello', ждать 100msec, считать ответ»

Примеры использования:

1. Отправить в Arduino один ASCII-символ «6»laptop% ./arduino-serial -b 9600 -p /dev/tty.usbserial -s 62. Отправить в Arduino строчку “furby”laptop% ./arduino-serial -b 9600 -p /dev/cu.usbserial -s furby3. Получить данные от Arduinolaptop% ./arduino-serial -b 9600 -p /dev/cu.usbserial -r read: 15 Hello world!

Данный пример показывает вывод данных от скетча

из проекта (Зловещий Ардуино). Отправить ASCII-строчку “get” в Arduino и получить результат:laptop% ./arduino-serial -b 9600 -p /dev/cu.usbserial -s get -r read: d=0

И немножко о внутреннем устройстве программы:

Там всего три интересных функции, которые показывают пример работы с последовательным портом на C:int serialport_init(const char* serialport, int baud)— получает имя порта (“/dev/tty.usbserial”,«COM1») и скорость работы, а возвращает файловый дескриптор открытого порта.

int serialport_write(int fd, const char* str)– отправляет в порт (по файловому дескриптору) строчку данныхint serialport_read_until(int fd, char* buf, char until)– считывает данные из последовательного порта в буфер, пока не встретит определённый символ (char until)

Arduino + C++ (using libSerial)

Работа с последовательным портом с использованием библиотеки

libSerial работает в POSIX-системах (на Windows работать не будет) подключение библиотеки:#include < SerialStream.h > #include < iostream > #define PORT “/dev/ttyUSB0″ // указывается порт, к которому подключена Arduino SerialStream ardu; using namespace std; using namespace LibSerial; примеры работы: void open() { ardu.Open(PORT); /*The arduino must be setup to use the same baud rate*/ ardu.SetBaudRate(SerialStreamBuf::BAUD_9600); ardu.SetCharSize(SerialStreamBuf::CHAR_SIZE_8); } int get(char out) { int res; char str[SOME_BIG_SIZE]; ardu > str; sscanf(str,”%d”,&res); return res; } Ссылки:

Arduino + C++ (for windows)

Источник: http://robocraft.ru/blog/arduino/76.html

Работа с Arduino из C# приложения

Дата публикации: 10.02.2016

В этой статье я хотел бы рассказать о том, как можно считывать данные и управлять платой Arduino, подключенной через USB порт, из .Net приложения и из приложения UWP.Делать это можно без использования сторонних библиотек. Фактически, используя только виртуальный COM порт.

Давайте сначала напишем скетч для Arduino.

Мы будем отправлять на порт строку с текстом, содержащим в себе значение переменной, которая у нас будет постоянно изменятся в цикле (таким образом имитируя данные снятые с датчика).

Также будем считывать данные с порта и в случае если получим текст «1», то включим встроенный в плату светодиод. Он расположен на 13-ом пине и помечен на плате латинской буквой L. А если получим «0», то выключим его.

int i = 0; // переменная для счетчика имитирующего показания датчика
int led = 13; void setup() { Serial.begin(9600); // установим скорость обмена данными pinMode(led, OUTPUT); // и режим работы 13-ого цифрового пина в качестве выхода
}
void loop() { i = i + 1; // чтобы мы смогли заметить что данные изменились String stringOne = “Info from Arduino “; stringOne += i; // конкатенация Serial.println(stringOne); // отправляем строку на порт char incomingChar; if (Serial.available() > 0) { // считываем полученное с порта значение в переменную incomingChar = Serial.read(); // в зависимости от значения переменной включаем или выключаем LED switch (incomingChar) { case '1': digitalWrite(led, HIGH); break; case '0': digitalWrite(led, LOW); break; } } delay(300);
}

WPF приложение

Теперь создадим WPF приложение. Разметку сделаем довольно простой. 2 кнопки и метка для отображения текста полученного с порта это все что необходимо:

Нет данных Послать 1 Послать 0

Добавим 2 пространства имен:

using System.Timers;
using System.IO.Ports;

И в области видимости класса 2 переменные с делегатом:

System.Timers.Timer aTimer;
SerialPort currentPort;
private delegate void updateDelegate(string txt);

Реализуем событие Window_Loaded. В нем мы пройдемся по всем доступным портам, прослушаем их и проверим не выводится ли портом сообщение с текстом «Info from Arduino». Если найдем порт отправляющий такое сообщение, то значит нашли порт Arduino. В таком случае можно установить его параметры, открыть порт и запустить таймер. 

bool ArduinoPortFound = false; try { string[] ports = SerialPort.GetPortNames(); foreach (string port in ports) { currentPort = new SerialPort(port, 9600); if (ArduinoDetected()) { ArduinoPortFound = true; break; } else { ArduinoPortFound = false; } } } catch { } if (ArduinoPortFound == false) return; System.Threading.Thread.Sleep(500); // немного подождем currentPort.BaudRate = 9600; currentPort.DtrEnable = true; currentPort.ReadTimeout= 1000; try { currentPort.Open(); } catch { } aTimer = new System.Timers.Timer(1000); aTimer.Elapsed += OnTimedEvent; aTimer.AutoReset = true; aTimer.Enabled = true;

Для снятия данных с порта и сравнения их с искомыми я использовал функцию ArduinoDetected:

private bool ArduinoDetected() { try { currentPort.Open(); System.Threading.Thread.Sleep(1000); // небольшая пауза, ведь SerialPort не терпит суеты string returnMessage = currentPort.ReadLine(); currentPort.Close(); // необходимо чтобы void loop() в скетче содержал код Serial.println(“Info from Arduino”); if (returnMessage.Contains(“Info from Arduino”)) { return true; } else { return false; } } catch (Exception e) { return false; } }

Теперь осталось реализовать обработку события таймера. Метод OnTimedEvent можно сгенерировать средствами Intellisense. Его содержимое будет таким:

private void OnTimedEvent(object sender, ElapsedEventArgs e) { if (!currentPort.IsOpen) return; try // так как после закрытия окна таймер еще может выполнится или предел ожидания может быть превышен { // удалим накопившееся в буфере currentPort.DiscardInBuffer(); // считаем последнее значение string strFromPort = currentPort.ReadLine(); lblPortData.Dispatcher.BeginInvoke(new updateDelegate(updateTextBox), strFromPort); } catch { } } private void updateTextBox(string txt) { lblPortData.Content = txt; }

Мы считываем значение с порта и выводим его в виде текста метки. Но так как таймер у нас работает в потоке отличном от потока UI, то нам необходимо использовать Dispatcher.BeginInvoke. Вот здесь нам и пригодился объявленный в начале кода делегат.

После окончания работы с портом очень желательно его закрыть. Но так как мы работаем с ним постоянно, пока приложение открыто, то закрыть его логично при закрытии приложения. Добавим в наше окно обработку события Closing:

private void Window_Closing(object sender, EventArgs e) { aTimer.Enabled = false; currentPort.Close(); }

Готово. Теперь осталось сделать отправку на порт сообщения с текстом «1» или «0», в зависимости от нажатия кнопки и можно тестировать работу приложения. Это просто:

private void btnOne_Click(object sender, RoutedEventArgs e) { if (!currentPort.IsOpen) return; currentPort.Write(“1”); } private void btnZero_Click(object sender, RoutedEventArgs e) { if (!currentPort.IsOpen) return; currentPort.Write(“0”); }

Получившийся пример доступен на  GitHub.

Кстати, WinForms приложение создается еще быстрее и проще. Достаточно перетянуть на форму из панели инструментов элемент SerialPort (при наличии желания можно перетянуть из панели инструментов и элемент Timer). После чего в нужном месте кода, можно открыть порт, считывать из него данные и писать в него примерно как и в WPF приложении.

UWP приложение

Для того чтобы разобраться с тем как работать с последовательным портом я рассмотрел следующий пример:  SerialSample
Для разрешения работы с COM портом в манифесте приложения должно быть такое вот объявление:

В коде C# нам понадобятся 4 пространства имен:

using Windows.Devices.SerialCommunication;
using Windows.Devices.Enumeration;
using Windows.Storage.Streams;
using System.Threading.Tasks;

И одна переменная в области видимости класса:

При загрузке считаем в нее значение id порта к которому подключена плата Arduino:

private async void Page_Loaded(object sender, RoutedEventArgs e) { string filt = SerialDevice.GetDeviceSelector(“COM3”); DeviceInformationCollection devices = await DeviceInformation.FindAllAsync(filt); if (devices.Any()) { deviceId = devices.First().Id; } }

Следующий Task считает 64 байта с порта и отобразит текст в поле с именем txtPortData

private async Task Listen() { using (SerialDevice serialPort = await SerialDevice.FromIdAsync(deviceId)) { if (serialPort != null) { serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000); serialPort.BaudRate = 9600; serialPort.Parity = SerialParity.None; serialPort.StopBits = SerialStopBitCount.One; serialPort.DataBits = 8; serialPort.Handshake = SerialHandshake.None; try { using (DataReader dataReaderObject = new DataReader(serialPort.InputStream)) { Task loadAsyncTask; uint ReadBufferLength = 64; dataReaderObject.InputStreamOptions = InputStreamOptions.Partial; loadAsyncTask = dataReaderObject.LoadAsync(ReadBufferLength).AsTask(); UInt32 bytesRead = await loadAsyncTask; if (bytesRead > 0) { txtPortData.Text = dataReaderObject.ReadString(bytesRead); txtStatus.Text = “Read operation completed”; } } } catch (Exception ex) { txtStatus.Text = ex.Message; } } } }

В UWP приложениях на C# отсутствует метод SerialPort.DiscardInBuffer. Поэтому один из вариантов, это считывать данные открывая каждый раз порт заново, что и было продемонстрировано в данном случае. Если вы попробуете, то сможете заметить, что отсчет каждый раз идет с единицы.

Примерно то же самое происходит и в Arduino IDE при открытии Serial Monitor. Вариант, конечно, так себе. Открывать каждый раз порт это не дело, но если данные необходимо считывать редко, то этот способ сойдет. Кроме того, таким образом записанный пример выглядит короче и понятнее.

Рекомендуемый вариант это не объявлять каждый раз порт заново, а объявить его один раз, например, при загрузке. Но в таком случае необходимо будет регулярно считывать данные с порта, чтобы он не заполнялся старьем и данные оказывались актуальными. Смотрите как это сделано в  моем примере UWP приложения.

Я так полагаю, что концепт отсутствия возможности очистить буфер состоит в том, что постоянно асинхронно снимаемые данные, не особо нагружают систему. Как только необходимое количество байт считывается в буфер, выполняется следом написанный код.

Есть плюс, в том, что при таком постоянном мониторинге ничего не пропустишь, но некоторым (и мне в том числе) не хватает привычной возможности один раз «считнуть» данные.

Для записи данных в порт можно использовать схожий код:

private async Task sendToPort(string sometext) { using (SerialDevice serialPort = await SerialDevice.FromIdAsync(deviceId)) { Task.Delay(1000).Wait(); if ((serialPort != null) && (sometext.Length != 0)) { serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000); serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000); serialPort.BaudRate = 9600; serialPort.Parity = SerialParity.None; serialPort.StopBits = SerialStopBitCount.One; serialPort.DataBits = 8; serialPort.Handshake = SerialHandshake.None; Task.Delay(1000).Wait(); try { using (DataWriter dataWriteObject = new DataWriter(serialPort.OutputStream)) { Task storeAsyncTask; dataWriteObject.WriteString(sometext); storeAsyncTask = dataWriteObject.StoreAsync().AsTask(); UInt32 bytesWritten = await storeAsyncTask; if (bytesWritten > 0) { txtStatus.Text = bytesWritten + ” bytes written”; } } } catch (Exception ex) { txtStatus.Text = ex.Message; } } } }

Читайте также:  Смартфон xiaomi redmi 3 от китайского гиганта - arduino+

Вы можете заметить, что после инициализации порта и установки параметров добавлены паузы по 1 секунде. Без этих пауз заставить Arduino среагировать не получилось. Похоже, что serial port действительно не терпит суеты. Опять же, напоминаю, что лучше открыть порт один раз, а не открывать/закрывать его постоянно. В таком случае никакие паузы не нужны. 

Упрощенный вариант UWP приложения, который аналогичен рассмотренному выше WPF .Net приложению доступен на  GitHub

В результате я пришел к выводу, что работа в UWP с Arduino напрямую через  виртуальный COM порт хоть и непривычна, но вполне возможна и без подключения сторонних библиотек. 

Замечу, что Microsoft довольно тесно сотрудничает с Arduino, поэтому различных библиотек и технологий коммуникации, упрощающих разработку, множество. Самая популярная, это конечно же работающая с протоколом Firmata библиотека  Windows Remote Arduino.

Источник: https://msdn.microsoft.com/ru-ru/mt661811.aspx

Пишем прошивку для Arduino на С++ с REST управлением через последовательный порт и экранчиком

Это второй пост про Wi-Fi роботанк. В нем будет написано как не надо делать прошивки, если вы суровый программист микроконтроллеров и как можно сделать, если нужна максимальная наглядность и возможность рулить прошивкой почти как веб-приложением прямо с терминала.

То есть, например, отправив в последовательный порт что-то типа

battery?act=status

получим в ответ что-то типа

{ “status”: “OK”, “minValue”: 600, “maxValue”: 900, “value”:750, “percent”: 50 }

Для тех, кому лень читать статью, сразу ссылка на github и Яндекс-диск, у кого гитхаб залочен (спасибо MaximChistov).

Итак, в какой-то момент я понял, что без ардуины мне никак не обойтись, достал из закромов Arduino Nano и купил к нему экранчик с I2C переходником.

Как я пытался подключить экран, это отдельная песня с припевом, но в итоге оказалось, что у меня был перебитый земляной провод и I2C адрес экрана не соответствовал ни одному из описаний в инете.

После успешного запуска HelloWorld из примеров я начал думать и что же мне со всем этим делать.

Что имелось в начале

На старте имелось следующее:

Список задач:

  1. Управление по типу HTTP REST
  2. Отображение на экране сообщений, уведомлений (больше приоритет) и иконок по типу system tray
  3. Определение уровня заряда батарейки
  4. Управление питанием и выстрелом пушки

Чуть-чуть про пушку и батарейку. Для определения уровня заряда я подключил плюс батарейки через делитель из 2х резисторов по 43КОм на вход A0. Осталось только откалибровать верхнее и нижнее значения. Пушка у меня включена не постоянно. При подаче единицы на цифровую ногу ардуины через полевой транзистор запитывается сервопривод наведения пушки и заодно лазерный прицел.

Для выстрела необходимо постепенно с помощью ШИМа (чтоб снизить помехи по питанию) открыть второй транзистор, включающий мотор самой пушки и также постепенно его выключить при замыкании контакта, который сигнализирует о том, что выстрел случился.
Также сразу уточню, что посмотрев на объем RAM у ATMega328, который всего 2 килобайта, я испугался и не стал использовать динамическую память.

Только стек, только хардкор.

Базовый скелет для обработки REST запросов

Поняв, что мне надо от ардуины и прогнав тестовые примеры, я радостно открыл Arduino IDE и завис. Мне явно было мало одного файла и хотелось нормального C++ с подсветкой и автокомплитом.

Через некоторое время пришло озарение.

Исходник оформляется в виде библиотеки, лежащей в sketchbook/libraries, а сам скетч создает единственный объект с методами Setup() и Loop() и соответственно их вызывает.

На всякий случай, уточню, что у Arduino SDK есть две абстракции ввода-вывода. Это Print, на который можно как это ни странно выводить и Stream, который унаследован от Print.

Базовые сущности получились такие:

  1. Команда. Создается из строки вида /commandName?arg1=value1&arg2=value2 и содержит простейший парсер аргументов.Интерфейсclass Command
    {
    public: Command( char* str ); inline const char* Name() const { return _name; } inline const char* Params() const { return _params; } const char* GetParam( const char* paramName ); bool GetIntParam( const char* paramName, int* out ); bool GetDoubleParam( const char* paramName, double* out ); bool GetStringParam( const char* paramName, const char** out ); private: char* _name; char* _params; size_t _paramsLen;
    };
  2. Обработчик команды. Обрабатывает команду и шлет ответ в виде JSON.Интерфейсclass CommandHandler
    {
    public: virtual void HandleCommand( Command& cmd, Print &output ); static void SendError( Print &output, const char* err ); static void SendOk( Print &output ); static void SendErrorFormat( Print &output, const char* fmt, … );
    };
  3. Обработчик запросов. Создает команду и маршрутизирует ее на соответствующий обработчик, если таковой есть.Интерфейсstruct HandlerInfo
    { const char* command; CommandHandler* handler; HandlerInfo(): command(0), handler(0) {} HandlerInfo(const char* c, CommandHandler* h): command(c), handler(h) {}
    }; class RequestHandler
    {
    public: RequestHandler(); void SetHandlers( HandlerInfo* handlers, size_t count ); void HandleRequest( char* request, Print& output ); private: HandlerInfo* _handlers; size_t _handlersCount;
    };

Для обработки запросов с последовательного порта (или еще какого Stream'a) был написан

StreamRequestHandlerclass StreamRequestHandler : public RequestHandler
{
public: static const size_t BufferSize = 128; StreamRequestHandler( Stream& stream ); void Proceed(); private: Stream& _stream; char _requestBuf[BufferSize]; size_t _requestLen;
};

Настало время все это протестировать. Для этого надо создать экземпляр StreamRequestHandler, передав ему в конструктор Serial (который на самом деле синглтон класса HardwareSerial), передать в SetHandlers массив обработчиков команд и дергать метод Proceed где-то внутри loop().
Первым обработчиком стал

PingHandlerclass PingHandler : public CommandHandler
{
public: virtual void HandleCommand( Command& cmd, Print &output ) { SendOk(output); }
};

Работа с экраном

После успешного отклика на пинг захотелось прочитать что-нибудь на экранчике и там же увидеть заряд батарейки. Стандартный экран 16×2 имеет, как ни странно, две строки по 16 символов, а также позволяет переопределить изображения для первых восьми символов.

Исходя из этого я решил первые 8 знакомест верхней строки отвести под system tray, вторые 8 пока не трогать, а все сообщения выводить в нижнюю строку.

Обычные сообщения будут выводиться бегущей строкой, а приоритетные будут не длиннее 16 символов и выводиться по центру, прерывая на время отображения, если надо, текущую бегущую строку.

Чтобы не городить связные списки на указателях, максимальное количество сообщений в очереди было ограничено до 8 обычных и 4 приоритетных, что позволило использовать для их хранения обычный кольцевой буфер.

Иконками в system tray стали обычные символы с кодами от 0 до 7. Для показа иконки надо сначала ее зарезервировать, получив iconID (который просто код символа), после чего для iconID можно задать само изображение. Анимированную иконку можно получить постоянно меняя картинку. Экран такое издевательство выдерживает без проблем.

Что в итоге получилосьclass DisplayController
{
public: static const uint8_t MaxIcons = 8; static const uint8_t Rows = 2; static const uint8_t Cols = 16; static const uint8_t IconsRow = 0; static const uint8_t IconsCol = 0; static const int MaxMessages = 8; static const unsigned MessageInterval = 150; static const uint8_t MessageRow = 1; static const uint8_t MessageCol = 0; static const uint8_t MessageLen = 16; static const int MaxAlerts = 4; static const unsigned AlertInterval = 1000; static const uint8_t AlertRow = 1; static const uint8_t AlertCol = 0; static const uint8_t AlertLen = 16; private: struct Message { const char* text; int length; int position; inline Message() { Clear(); } inline void Clear() { text = 0; length = 0; position = 0; } }; struct Alert { const char* text; int length; bool visible; inline Alert() { Clear(); } inline void Clear() { text = 0; length = 0; visible = false; } }; public: DisplayController( uint8_t displayAddr ); void Init(); int8_t AllocateIcon(); void ReleaseIcon(int8_t iconId); void ChangeIcon(int8_t iconId, uint8_t iconData[]); void UpdateIcons(); void Proceed(); bool PutMessage( const char* text ); bool PutAlert( const char* text ); inline bool HasMessages() { return _messages[_messageHead].text != 0; } inline bool HasAlerts() { return _alerts[_alertHead].text != 0; } void UpdateMessage(); void UpdateAlert(); private: LiquidCrystal_I2C _lcd; int _iconBusy; unsigned long _messageTick; Message _messages[MaxMessages]; int _messageHead; int _messageTail; unsigned long _alertTick; Alert _alerts[MaxAlerts]; int _alertHead; int _alertTail;
};

А дальше все банально

Осталось только дописать логику обработчиков команд и зарегистрировать их в маршрутизаторе. Обработчиков, кроме PingHandler получилось целых три: батарейка, пушка и общий статус всего и сразу. Особого интереса они не представляют, поэтому, кому интересно, просто гляньте исходник.

В планах на будущее допиливание DisplayController, чтоб тот мог показывать не только константные строки, но и например строки, полученные как параметры команды.

Проблема тут в том, что нету никакого освобождения памяти и сигнализации о том, что сообщение отображено и удалено из DisplayController.

Также планирую дописать обработчик, который будет показывать в трее микрофон и динамик при подключении соответствующего звукового канала.

Собственно, все, спасибо за внимание. Надеюсь, что кому-нибудь мой опыт пригодится. Весь код, кроме скетча лежит на github'е или на Яндекс-диске, а сам скетч выглядит так:

Скетч

Источник: http://www.pvsm.ru/arduino/76365

Справочник по C++ для Arduino

Справочник по C++ для Arduino [Apr. 8th, 2010|06:48 pm]Cообщество любителей Arduino
[]

Наконец-то дошли руки начать переписывать скетч, работающий с жк-экраном. Пытаюсь привести его к виду библиотечки. К сожалению, у меня нет информации о специфике cpp-программ для Arduino. Во входящем в дистрибутив Arduino IDE справочнике (/reference) есть много лбопытного, но ничего не сказано ни о , ни о том, как вообще здесь принято динамически работать с памятью. Посоветуйте “продвинутый” справочник/учебник по программированию для Arduino на C++ – чтобы в нем подробно описывались разнообразные аспекты программирования для Arduino. Ну вот хотя бы как динамически отвести страницу видеопамятиbyte* _lcdScreen = (byte *)alloc(_lcdScreenWidth * _lcdScreenHeight);?

Comments:
From: ben_tal2010-04-08 03:12 pm (UTC) (Link)

сомневаюсь, что динамическая работа с памятью поддерживается… уж слишком хилые ресурсы у контроллера. да и динамическое управление памятью обычно прерогатива ОС а не С-рантайм библиотеки. она лишь раппер в данном случае.
думаю можно спросить Arduino Forum – Index — там разработчики бывают…
или самому написать… а зачем? почему не статически?

From: telegamochka2010-04-08 03:33 pm (UTC) (Link)

Так как используемый мною дисплей в последовательном режиме не позволяет читать из видеопамяти, то для того, чтобы рисовать на экране (а не просто выводить туда готовую картинку), мне приходится заводить “видеопамять” на ардуине.

Графическая видеостраница просто не поместится в оперативке (128*64/8 = 1024 байта), поэтому я реализовала текстовый режим с минимальным набором псевдографики. Размер моего шрифта – 4*8, так что видеостраница занимает 32*8=256 байт.

В библиотеке я хочу дать возможность использовать не только мой (компактный, но трудночитаемый) шрифт, но и другие, например, 5*8, 6*8 или 8*8. При этом размер страницы видеопамяти будет меньше.

Именно поэтому при инициализации текстового режима я хотела сделать так, чтобы библиотеке передавались указатель на данные шрифта и размеры символа. А библиотека использовала бы для видеопамяти ровно столько, сколько нужно.

From: potan2010-04-08 03:53 pm (UTC) (Link)

Шрифт можно реализовать функциями, рисующими каждую букву. Памяти кода там заметно больше, чем памяти данных – может компактно и читабельно получиться.

From: telegamochka2010-04-08 04:22 pm (UTC) (Link)

А в чем выигрыш при таком подходе? Только проигрыш в коде. В принципе, можно оставить в библиотечке только функции вывода символов, безо всякой видеопамяти. Ее, если нужно, программер сам реализует в своем коде. Пожалуй, так и сделаю.

From: ben_tal2010-04-08 04:36 pm (UTC) (Link)

тогда, если не найдёте, писать самой… вряд ли кто захочет часто менять шрифт в рантайме, значит аллокация одноразово, в ините… не смертельно…

From: ben_tal2010-04-08 04:37 pm (UTC) (Link)

и бывают ардуины с “большой” оперативкой. там и 1к можно взять…

From: pasha_e2010-04-23 08:34 am (UTC) (Link)

а вы не подскажете, я вот где то видел когда то ссылку на среду, чтобы под ардуино программить на человеческом С/С++, а не том что предлагается. Но ен могу найти 🙁 Не встречали?

From: telegamochka2010-04-26 01:08 pm (UTC) (Link)

Судя по всему, это AVR Studio: http://www.atmel.com/dyn/products/tools_card_v2.asp?tool_id=4116
Может быть, стоит погуглить статьи по работе с этой IDE. Я пока работаю с Arduino IDE, параллельно читаю “Самоучитель разработчика устройств на микроконтроллерах AVR”. Возможно, через некоторое время перейду с ардуиньего наречия на C/Asm – благо и с тем, и с другим давно знакома, правда, для Z80/x86 🙂

From: 0x82010-04-28 09:35 am (UTC) (Link)

Да нету “человеческого С++” на такой архитектуре. С такими аппаратными ограничениями С++ обходится слишком дорого. Только чистый С.
В родной среде С компайлер и стоит + Ардуино библиотека. В качестве среды можно Eclipse прикрутить.

From: pasha_e2010-04-28 11:52 am (UTC) (Link)

да понятно что контроллер он и в африке контроллер. можно хоть в кодВижн, хоть в винАВР и грузить через ISP разъём. только с фьюзами и настройками надо аккуратненько. Думал может есть среда заточенная где нибудь, чтоб всё прописано было, без лишнего кулибинства,и через usb.

Источник: https://ru-arduino.livejournal.com/15802.html

Язык программирования в Arduino

Концепция программирования: Программирование ведется целиком через собственную программную оболочку (IDE), бесплатно доступную на сайте Arduino. В этой оболочке имеется текстовый редактор, менеджер проектов, препроцессор, компилятор и инструменты для загрузки программы в микроконтроллер. Оболочка написана на Java на основе проекта Processing, работает под Windows, Mac OS X и Linux.

Язык программирования в Arduino

Язык программирования Arduino является стандартным C++ (используется компилятор AVR-GCC) с некоторыми особенностями, облегчающими новичкам написание первой работающей программы.

  • Программы, написанные программистом Arduino называются наброски (или иногда скетчи — калька от англ. sketch) и сохраняются в файлах с расширением ino. Эти файлы перед компиляцией обрабатываются препроцессором Ардуино. Также существует возможность создавать и подключать к проекту стандартные файлы C++.
  • Обязательную в C++ функцию main() препроцессор Arduino создает сам, вставляя туда необходимые «черновые» действия.
  • Программист должен написать две обязательные для Arduino функции setup() и loop(). Первая вызывается однократно при старте, вторая выполняется в бесконечном цикле.
  • В текст своей программы (скетча) программист не обязан вставлять заголовочные файлы используемых стандартных библиотек. Эти заголовочные файлы добавит препроцессор Arduino в соответствии с конфигурацией проекта. Однако пользовательские библиотеки нужно указывать.
  • Менеджер проекта Arduino IDE имеет нестандартный механизм добавления библиотек. Библиотеки в виде исходных текстов на стандартном C++ добавляются в специальную папку в рабочем каталоге IDE. При этом название библиотеки добавляется в список библиотек в меню IDE. Программист отмечает нужные библиотеки и они вносятся в список компиляции.
  • Arduino IDE не предлагает никаких настроек компилятора и минимизирует другие настройки, что упрощает начало работы для новичков и уменьшает риск возникновения проблем.

Простейшая Arduino-программа состоит из двух функций:

  • setup(): функция вызывается однократно при старте микроконтроллера.
  • loop(): функция вызывается после setup () в бесконечном цикле все время работы микроконтроллера.

Одна из простейших схем на Arduino — это подключение внешнего светодиода, управление которым происходит при помощи программы (скетча).

Так выглядит полный текст простейшей программы (скетча) мигания светодиодом, подключенного к 13 выводу Arduino, с периодом 2 секунды[15]:

void setup () {

pinMode (13, OUTPUT); // Назначение 13 вывода Arduino выходом

}

void loop () {

digitalWrite (13, HIGH); // Включение 13 вывода, параметр вызова функции digitalWrite HIGH – признак высокого логического уровня

delay (1000); // Цикл задержки на 1000 мс – 1 секунду

digitalWrite (13, LOW); // Выключение 13 вывода, параметр вызова LOW – признак низкого логического уровня

delay (1000); // Цикл задержки на 1 секунду

}

Все используемые в примере функции являются библиотечными. В комплекте Arduino IDE имеется множество примеров программ. Существует перевод документации по Arduino на русский язык[16][17].

Загрузка программы в микроконтроллер

Закачка программы в микроконтроллер Arduino происходит через предварительно запрограммированный специальный загрузчик (все микроконтроллеры от Ардуино продаются с этим загрузчиком). Загрузчик создан на основе Atmel AVR Application Note AN109.

Загрузчик может работать через интерфейсы RS-232, USB или Ethernet в зависимости от состава периферии конкретной процессорной платы.

В некоторых вариантах, таких как Arduino Mini или неофициальной Boarduino, для программирования требуется отдельный переходник.

Пользователь может самостоятельно запрограммировать загрузчик в чистый микроконтроллер. Для этого в IDE интегрирована поддержка программатора на основе проекта AVRDude. Поддерживается несколько типов популярных дешёвых программаторов.

Источник: https://webhamster.ru/mytetrashare/index/mtb0/1498801946cmgre8eug6

Как лучше организовать взаимодействие с настольным Qt/C++ Application через интернет?

Предложу три варианта взаимодействия через Web: 1. Соединение “клиент-сервер-клиент”. в интернете организовывается простейший HTTP сервер. На него ложится CGI-скрипт, который принимает запросы от управляющего устройства и складывает их в файл. Второе (управляемого) устройство периодически скачивает с сервера запросы и отвечает на них – ответы также складируются на сервере.

А затем управляющее устройство выгребает их. Это классический случай, в принципе тут ничего сложного и страшного нет. Но главный минус – real-time'a не получится. Задержки будут в пару секунд 2. Соединение “клиент-клиент через IPv4”.

Управляющий и управляемый компьютер каким-то образом договариваются о соединении между собой – с целью преодоления всевозможных NAT'ов и файрволлов. А затем обмениваются данными между собой. Плюс – real-time, минус – сложные решения для организации начального соединения.

Причём минус жирный – для embedded устройств, особенно без полноценной поддержки сетевого стека и сторонних утилит для сети это организовать очень сложно. 3. Соединение “клиент-клиент через IPv6”. Поскольку сеть – IPv6, то не нужно заморачиваться о преодолении NAT'ов – в IPv6 к любому устройству можно достучаться напрямую. Код совсем минимальный.

Минус – IPv6 пока не сильно развит, но есть много сервисов, позволяющих пробросить IPv6 через IPv4. Но это требует установки дополнительного софта.

Так что решайте – стоит ли мучаться с Arduino, или же проще взять что-то помощнее, нп. тот же RaspberryPi и ему подобных товарищей

Нравится 1 5 комментариев

Если у вас нет опыта работы с сокетами, то лучше и не беритесь. Воспользуйтесь протоколом более высокого уровня: HTTP, в качестве формата данных json. Не совсем понятно, что вкладывается в понятие “взаимодействие c Arduino”, возможно вам потребуется что-то вроде WebSockets, если это взаимодействие может происходить с любой стороны.

Вот что я подразумеваю под взаимодействием с Arduino. Например Arduino чем-то управляет и я хочу воспользоваться управлением Arduino через браузер.

Я открываю браузер, набираю адрес и вижу страницу, на которой в реальном времени отображаются какие-то меняющиеся показатели, приходящие с Arduino (температура и прочее).

Также на этой странице есть кнопочки, которые я могу нажимать и в следствии нажатия на одну из них Arduino должна отреагировать на эти нажатия соответствующим образом. То есть Вы предлагаете посылать HTTP-запросы.

Если я буду посылать запросы каждые 100 миллисекунд ничего страшного не произойдет? Просто не встречался с этим.

А как же поступить с входящими пакетами, которые формируются при взаимодействии с веб-интерфейсом по средствам кнопочек. Как их посылать на управляющий компьютер? Ответами на запросы? Пока не могу понять.

Размышляя о перспективах, я подумал, что хочу найти достаточно универсальный вариант общения с сервером. Чтобы, я например, имея операционную систему типа linux, android, windows на каком-либо устройстве с интернет соединением, мог общаться с сервером одинаковым образом для каждой из ОС. Ведь для каждой ОС есть реализация сокетов.

Мне кажется, что это самый лучший вариант. Проблема только в том, что нужен хостинг с возможностью запуска свой собственной программы, например на С++, которая бы обрабатывал запросы по сокету. Лучше конечно общаться через php-скрипт, который будет работать на более дешевом хостинге. Конечно, это размышление чистого новичка в вебе.

Так я сразу и хотел использовать linux-сокеты на плюсах. Проблема в том, где взять такой хостинг, чтобы можно было запускать в терминале любые команды и программы и чтобы он ещё был бесплатный или хотя бы не дорогой. Тем более я ещё даже домен не нашел. Искал бесплатный 3-его уровня, но так и не нашел где заказать.

Поэтому пока приходится проводить испытания на локальном сервере. Вторая загвоздка в том, что я пока не имею полного представления о взаимодействии собственной программы на сервере и клиента. Пока у меня перед глазами такая картина. Есть программа на плюсах, которая в отдельном потоке получает запросы и отвечает на них.

Всё это происходит без остановки в реальном времени (с допустимыми для меня задержками). Тут у меня возникает трудность. Как организовать запрос от js/html клиента через jquery-ajax на сервер к программе на плюсах? Я пока только имел опыт отправки ajax-post запроса php-скрипту, который в ответ через echo отдавал json-строку.

Обновление данных происходило только после перезагрузки страницы. Как сделать запросы клиента циклическими в отдельном потоке? Или придётся формировать html-документ вручную на сервере на плюсах? Сейчас я экспериментирую и пробую обойтись php-скриптом.

Уже получил двустороннюю связь, запуская php-скрипт просто в консоли, отдельно от браузера. Однако пока остаётся та же проблема.

А именно, как со стороны клиента делать асинхронные непрерывные запросы к php-скрипту, который крутится в процессах и отдаёт json-строку?

Все мои сложности из-за непонимания взаимодействия сервера и клиента на уровне ОС. Уровень браузера не может дать мне полного представления. Что посоветуете на эту тему?

Источник: https://toster.ru/q/66148

Управление светодиодами при помощи программы на C# и Arduino

Вам никогда не хотелось управлять СИД, подключенными к Arduino, с помощью программы, которую вы же и написали? Так вот, я здесь, чтобы помочь вам с этим. Это моя первая статья, так что, прошу подсказать, если я что-то напутал. Ну и можете спокойно изменять мой код под свои нужды.

Нам потребуется:

  1. Плата Arduino
  2. Макетная плата
  3. Провода папа-папа

Шаг 1

Откройте Microsoft Visual Studio 2010 или Microsoft Visual Studio С# 2010 и создайте новый C# проект. Назовите его произвольным именем/названием. После этого нажмите ОК

Шаг 2

Для этого примера я сделаю две простеньких кнопки, чтобы управлять включением и выключением СИД, подключенного на 13 пин. Для начала откройте «Панель элементов» и перетащите элемент «кнопка» на рабочую область. Повторите. Добавьте две панели и измените их размеры, должно получиться приблизительно как на рисунке.

Так же добавьте последовательный порт из той же «Панели элементов»

Шаг 3. Переименуем кнопки

Вы можете переименовать свои кнопки или оставить как есть. Я оставил как есть, но изменил текст на них. Чтобы сделать это, нажимаете на кнопку, затем в правой части окна, в окне «Свойства», в строке «Текст» изменяете текст. На скриншоте можно увидеть это поле. В локализованных версиях название может отличаться.  Убедитесь, что изменяете именно ту кнопку.

Шаг 4. Добавляем код

Дважды нажмите на кнопку «On». У вас должно будет появиться окно похожее на то, что на скриншоте. Теперь, в блоке для кода вставьте следующее:

serialPort1.Open();

if (serialPort1.IsOpen)

{

serialPort1.WriteLine(“A”);

}

serialPort1.Close();

panel1.BackColor = Color.Lime;

panel2.BackColor = Color.Transparent;

Поднимитесь выше по коду до:

public Form1()

{

}

Ивставьтеследующее

InitializeComponent();

serialPort1.PortName = ”    “;

serialPort1.BaudRate = 9600;

междускобками.

Параметры для PortName мы добавим позже.

Теперь вернемся в «Конструктор», выделим кнопку «Off» и добавим следующий код:

serialPort1.Open();

if (serialPort1.IsOpen)

{

serialPort1.WriteLine(“a”);

}

serialPort1.Close();

panel2.BackColor = Color.Red;

panel1.BackColor = Color.Transparent;

Шаг 5. Код для Arduino

Так, хорошо, для того, чтобы написать код под Arduino, нам необходимо получать сообщения через последовательный порт. И есть только один путь осуществления этого, который я знаю. Извините, если есть и другие варианты – я только начинаю работать с Arduino.

int message = 0;    // Резерв одного байта для сообщений через последовательный порт

int LEDPin = 13;    // Пин, к которому подключен СИД

int LED = 0;        // Параметр значения яркости СИД, может принимать значения 0-255

void setup() { 

  Serial.begin(9600);  //открытие последовательного порта со скоростью передачи данных 9600 бит/с

}

void loop(){

    if (Serial.available() > 0) { //  Проверка, нет ли новых сообщений

      message = Serial.read();    //  Послатьсообщениенапоследовательныйпорт Put the serial input into the message

   if (message == 'A'){  //  Если буква «А» получена в верхнем регистре

     LED = 255;       //  Установить яркость СИД 255 (включить его)

     Serial.println(“LED on”);  // Отправить «LED on»

   }

   if (message == 'a'){  //  Если буква «А» получена в нижнем регистре

     LED = 0;         //  Установить яркость СИД 0 (выключить его)

     Serial.println(“LED off”);  // Отправить «LED off»

   }

    }

}

Шаг 6. Установка

Для начала вам нужно взять СИД и подключить его к Arduino, как показано на фото. Убедитесь, что анод (+) подключен к 13 пину, а катод (-) к земле.

Затем откройте Arduino IDE и вставьте код из вложения ниже. Затем в меню выберите «Инструменты». В разделе «Плата» убедитесь, что выбрана та, которую вы используете. У меня это – Dueminelove. В разделе «Порт» убедитесь, что выбран верный порт. У меня это – COM4.

Простите, за плохое качество фотографий, но делал я их на телефон. Фотоаппарат сломался этим утром.

Шаг 7. Добавляем последовательный порт в программу C#

Вернитесь к C# проекту и найдите там строку

serialPort1.PortName = ”   “;

и в пустое место между кавычками вставьте номер последовательного порта.

Затем вам нужно вернуться в конструктор и нажать на изображение последовательного порта в левом нижнем углу. В окне свойств измените PortName на то, что вы вписали в код. В моем случае это – СОМ4.

Шаг 8. Тестирование

Загрузите скетч на плату Arduino и проверьте его с помощью монитора последовательного порта. Напечатайте букву «А» в верхнем регистре, чтобы включить СИД, и в нижнем, чтобы выключить.

Вернитесь в C# программу и запустите отладку. Это можно сделать, нажав значок проигрывания на панели меню, или нажав F5. Затем нажмите на кнопку «On». Должен загореться СИД. Нажмите на «Off» – и он потухнет.

Вуаля! Вы создали программу, которая может общаться с Arduino!

Можете добавить еще несколько СИД и даже функционала! Развлекайтесь!

Ниже я прикрепил фото моего контроллера. Было весело!

Я прикрепил код и то, что не было освещено в статье.

Материалы для данной статьи и скриншоты в высоком качестве можно найти тут: https://yadi.sk/d/6LxChdD1kvjpK

Перевод статьи: http://www.instructables.com/id/Controll-Leds-With-an-Arduino-From-a-C-Program/?ALLSTEPS

Лицензия: CC BY-SA-2.5

Источник: https://tpai.ru/blog/perevody-statej/upravlenie-svetodiodami-pri-pomosshi-programmy-na-c-i-arduino

Коммуникация между программой на Visual c++ и arduino через usb

Для коммуникации с ардуиной можно использовать встроенные средства. Создаем пустой проект на языке Visual C++

Добавляем форму в проект. Правой кнопкой мыши в Solution Explorer на проекте Add->New Item. UI->Windows Form

Потом студия спросит о конвертации в CLR, соглашаемся. Далее необходимо заменить содержимое файла MyForm.cpp на

#include “MyForm.h” using namespace System; using namespace System::Windows::Forms; [STAThread] void main(array

Далее нужно задать точку входа Это делается в свойствах проекта в поле Entry Point вписать main

Код формы на Visual C++ MyForm.h

#pragma once namespace serial_remote { using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; using namespace System::IO::Ports; /// public ref class MyForm : public System::Windows::Forms::Form { public: int servo1pos; int servo2pos; int servo3pos; bool nonNumberEntered; MyForm(void) { InitializeComponent(); // //TODO: Add the constructor code here // } protected: /// ~MyForm() { if (components) { delete components; } } private: System::Windows::Forms::Label^ label7; private: System::Windows::Forms::Label^ label8; private: System::Windows::Forms::Label^ label9; private: System::Windows::Forms::RichTextBox^ richTextBox1; private: System::Windows::Forms::Label^ label10; private: System::Windows::Forms::GroupBox^ groupBox1; private: System::Windows::Forms::Button^ button2; private: System::Windows::Forms::Button^ button1; private: System::Windows::Forms::TextBox^ textBox2; private: System::Windows::Forms::Label^ label2; private: System::Windows::Forms::TextBox^ textBox1; private: System::Windows::Forms::Label^ label1; private: System::Windows::Forms::GroupBox^ groupBox2; private: System::Windows::Forms::Button^ button3; private: System::Windows::Forms::Button^ button4; private: System::Windows::Forms::TextBox^ textBox3; private: System::Windows::Forms::Label^ label3; private: System::Windows::Forms::TextBox^ textBox4; private: System::Windows::Forms::Label^ label4; private: System::Windows::Forms::GroupBox^ groupBox3; private: System::Windows::Forms::Button^ button5; private: System::Windows::Forms::Button^ button6; private: System::Windows::Forms::TextBox^ textBox5; private: System::Windows::Forms::Label^ label5; private: System::Windows::Forms::TextBox^ textBox6; private: System::Windows::Forms::Label^ label6; private: System::ComponentModel::IContainer^ components; protected: private: /// #pragma region Windows Form Designer generated code /// void InitializeComponent(void) { this->groupBox1 = (gcnew System::Windows::Forms::GroupBox()); this->label7 = (gcnew System::Windows::Forms::Label()); this->button2 = (gcnew System::Windows::Forms::Button()); this->button1 = (gcnew System::Windows::Forms::Button()); this->textBox2 = (gcnew System::Windows::Forms::TextBox()); this->label2 = (gcnew System::Windows::Forms::Label()); this->textBox1 = (gcnew System::Windows::Forms::TextBox()); this->label1 = (gcnew System::Windows::Forms::Label()); this->groupBox2 = (gcnew System::Windows::Forms::GroupBox()); this->label8 = (gcnew System::Windows::Forms::Label()); this->button3 = (gcnew System::Windows::Forms::Button()); this->button4 = (gcnew System::Windows::Forms::Button()); this->textBox3 = (gcnew System::Windows::Forms::TextBox()); this->label3 = (gcnew System::Windows::Forms::Label()); this->textBox4 = (gcnew System::Windows::Forms::TextBox()); this->label4 = (gcnew System::Windows::Forms::Label()); this->groupBox3 = (gcnew System::Windows::Forms::GroupBox()); this->label9 = (gcnew System::Windows::Forms::Label()); this->button5 = (gcnew System::Windows::Forms::Button()); this->button6 = (gcnew System::Windows::Forms::Button()); this->textBox5 = (gcnew System::Windows::Forms::TextBox()); this->label5 = (gcnew System::Windows::Forms::Label()); this->textBox6 = (gcnew System::Windows::Forms::TextBox()); this->label6 = (gcnew System::Windows::Forms::Label()); this->richTextBox1 = (gcnew System::Windows::Forms::RichTextBox()); this->label10 = (gcnew System::Windows::Forms::Label()); this->groupBox1->SuspendLayout(); this->groupBox2->SuspendLayout(); this->groupBox3->SuspendLayout(); this->SuspendLayout(); // // groupBox1 // this->groupBox1->Controls->Add(this->label7); this->groupBox1->Controls->Add(this->button2); this->groupBox1->Controls->Add(this->button1); this->groupBox1->Controls->Add(this->textBox2); this->groupBox1->Controls->Add(this->label2); this->groupBox1->Controls->Add(this->textBox1); this->groupBox1->Controls->Add(this->label1); this->groupBox1->Location = System::Drawing::Point(12, 12); this->groupBox1->Name = L”groupBox1″; this->groupBox1->Size = System::Drawing::Size(237, 393); this->groupBox1->TabIndex = 0; this->groupBox1->TabStop = false; this->groupBox1->Text = L”Серво 1″; // // label7 // this->label7->AutoSize = true; this->label7->Font = (gcnew System::Drawing::Font(L”Microsoft Sans Serif”, 12, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point, static_cast

Форма будет выглядеть так

В данном случае вместо серво приводов используется мой любимый трех цветный сведодиод

Теперь напишем скетч для ардуины

String readString; int red= 13;
int green= 12;
int blue= 11; int servo1pos, servo2pos, servo3pos; // the setup routine runs once when you press reset:
void setup() { // initialize the digital pin as an output. pinMode(red, OUTPUT); pinMode(green, OUTPUT); pinMode(blue, OUTPUT); Serial.begin(9600); } // the loop routine runs over and over again forever:
void loop() { while (Serial.available()) { delay(3); //delay to allow buffer to fill if (Serial.available() >0) { char c = Serial.read(); //gets one byte from serial buffer readString += c; //makes the string readString } } if (readString.length() >0) { Serial.println(readString); //see what was received int commaIndex = readString.indexOf(' '); int secondCommaIndex = readString.indexOf(' ', commaIndex+1); String firstValue = readString.substring(0, commaIndex); String secondValue = readString.substring(commaIndex+1, secondCommaIndex); String thirdValue = readString.substring(secondCommaIndex); servo1pos = firstValue.toInt(); servo2pos = secondValue.toInt(); servo3pos = thirdValue.toInt(); if (servo1pos > 40) { digitalWrite(green, HIGH); // turn the LED on (HIGH is the voltage level) } else { digitalWrite(green, LOW); // turn the LED off by making the voltage LOW } if (servo2pos > 40) { digitalWrite(blue, HIGH); // turn the LED on (HIGH is the voltage level) } else { digitalWrite(blue, LOW); // turn the LED off by making the voltage LOW } if (servo3pos > 40) { digitalWrite(red, HIGH); // turn the LED on (HIGH is the voltage level) } else { digitalWrite(red, LOW); // turn the LED off by making the voltage LOW } } //очистим строку readString = “”;
}

Как это работает

Источник: http://dzlife.ru/2016/02/15/5/

Ссылка на основную публикацию
Adblock
detector