#1 2016-03-02 18:23:39

ardnew
Учасник
Зареєстрований: 2016-03-02
Повідомлень: 62

помогите новичку пожалуйста !

помогите пожалуйста, с компьютера на ардуино поступают команды в таком виде: "Rele 1", "Rele 2", "Rele 3" (изменить их нельзя)
написал такой код:

   if (Serial.available() > 0)
  {
   char str = Serial.read(); 
    if (str == 'Rele 1') digitalWrite(led11, HIGH);
    if (str == 'Rele 2') digitalWrite(led12, HIGH);
    if (str == 'Rele 3') digitalWrite(led13, HIGH);
  }

но не работает, что делаю не так ?
заранее признателен за помощь !

Неактивний

#2 2016-03-02 18:39:55

NoName
Customer
З Київ
Зареєстрований: 2014-07-08
Повідомлень: 1,446

Re: помогите новичку пожалуйста !

вы   делаете вычитку по байту
и байт сравниваете со строкой
Вам нужно читать строки
https://www.arduino.cc/en/Serial/ReadString
либо самому собирать строку

несколько вариантов в ответах
http://stackoverflow.com/questions/1119 … on-arduino

Неактивний

#3 2016-03-02 19:09:27

ardnew
Учасник
Зареєстрований: 2016-03-02
Повідомлень: 62

Re: помогите новичку пожалуйста !

NoName пише:

вы   делаете вычитку по байту
и байт сравниваете со строкой
Вам нужно читать строки
https://www.arduino.cc/en/Serial/ReadString
либо самому собирать строку

несколько вариантов в ответах
http://stackoverflow.com/questions/1119 … on-arduino

по последней ссылке нашел похожий пример, ну что то опять не хочет работать, что опять не так делаю ?

int x;
String str;

  void setup(){
    Serial.begin(9600);
  }
     
      if (Serial.available() > 0)
  {
        str = Serial.readStringUntil('\n');
        x = Serial.parseInt();
    if (x == 'Rele 1') digitalWrite(led11, HIGH);
    if (x == 'Rele 2') digitalWrite(led12, HIGH);
    if (x == 'Rele 3') digitalWrite(led13, HIGH);
    }

Остання редакція ardnew (2016-03-02 19:09:47)

Неактивний

#4 2016-03-02 20:03:59

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: помогите новичку пожалуйста !

char input[20];
  void setup(){
    Serial.begin(9600);
  }
void loop()
{   
      if (Serial.available() > 0)
  {
    Serial.readBytes( input, 20 );
    String str= (String) input;
    if (str == "Rele 1") digitalWrite(led11, HIGH);
    if (str == "Rele 2"') digitalWrite(led12, HIGH);
    if (str == "Rele 3") digitalWrite(led13, HIGH);
    }
}
может где то так  smile

Неактивний

#5 2016-03-02 20:38:11

NoName
Customer
З Київ
Зареєстрований: 2014-07-08
Повідомлень: 1,446

Re: помогите новичку пожалуйста !

if (x == 1) digitalWrite(led11, HIGH);
    if (x == 2) digitalWrite(led12, HIGH);
    if (x == 3) digitalWrite(led13, HIGH);

??
и это не нравится, 
  if (Serial.available() > 0)
есть ли проверка на строку?

Остання редакція NoName (2016-03-02 20:38:27)

Неактивний

#6 2016-03-02 22:16:46

ardnew
Учасник
Зареєстрований: 2016-03-02
Повідомлень: 62

Re: помогите новичку пожалуйста !

Nefreemen пише:

может где то так  smile

точно! так работает! спасибо большое за помощь !

Остання редакція ardnew (2016-03-02 22:37:05)

Неактивний

#7 2016-03-03 10:45:11

NoName
Customer
З Київ
Зареєстрований: 2014-07-08
Повідомлень: 1,446

Re: помогите новичку пожалуйста !

Nefreemen, что то я чую, что логическую бомбу заложили )
кто спец по либам, обьясните

предположим пришло 4 байта, разрыв в потоке, бывает, это ведь асинхронный поток
if (Serial.available() > 0)
4 больше нуля, поехали дальше
Serial.readBytes( input, 20 );
читаем 20 байт, но если их нет то по таймауту отдаем сколько есть и очищаем буфер, я бы так делал
т.е. если набивать ручками управляющие команды то будет кака?  или как эта либа работает?

Неактивний

#8 2016-03-03 11:39:40

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: помогите новичку пожалуйста !

NoName, да поток асинхронный, таймаут  по умолчанию 1000мс ( и его всегда можно изменить smile ). Даже при скорости 9600 бод сколько байт придет, или может прийти учитывая какие то паузы? Правильно намного больше нежели 20 байт big_smile . Для простых задач, типа этой, этого вполне достаточно. Если вести речь о передаче больших объемов например файла, то алгоритм ясное дело другой, это может быть проверка на полноту полученной информации  по контрольной суме или другие "фантазии" программиста. Не мне Вам рассказывать big_smile . А для передачи управляющей команды это надо? Ну получит раз на тысячу в буфере вместо "Relay 1" что то типа Rela или Pelay lol . Реактивный двигатель не запуститься и спутник упадет lol ? А новичку само то, и "аппетит" не испортить, и в очень сложные дебри пока не влезать  big_smile (всему свое время). Я как и Вы понимаю, что в идеале можно замутить типа контроль по int как признак окончания передачи ( поскольку в передаче нельзя ничего изменить, добавить что то типа % или }). Можно читать по байтам в строку и контролировать длину. И мало что можно придумать lol . Новичок сам когда то придет к этому но в других задачах big_smile .

Неактивний

#9 2016-03-03 12:01:40

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: помогите новичку пожалуйста !

Да к стати, о Serial и двух вечерах убитого времени. Задача банальная. Передаю ISON строку из Arduino 2560 в ESP все путем. Возвращаю ее с изменениями обратно, и тут облом, приходит только часть. Причем обрывается по разному, увеличиваю буфер ISON - не идет. Возился долго, нудно пока не сделал подсчет байтов и тут "сюприз" - 63 байта хоть тресни. Лезу в библиотеку Serial смотрю вроде все ОК при разных объемах остатка флеша разный кольцевой буфер. Но черт возьми при загрузке в 15% Atmega2560 у меня получается 64 sad . Ставлю ручками 256 байт и все начало бегать как дети в школу. Вот такие бывают "сюрпризы" в библиотеках lol .

Неактивний

#10 2016-03-03 12:52:56

NoName
Customer
З Київ
Зареєстрований: 2014-07-08
Повідомлень: 1,446

Re: помогите новичку пожалуйста !

возьмет кто то такой пример - а не работает,  и будет Nefreemenу икаться ) ибо вспоминать будут незлым, тихим, словом )
учится нужно на правильных алгоритмах, трудноуловимые глюки - бичЪ программиста )

Неактивний

#11 2016-03-03 13:12:31

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: помогите новичку пожалуйста !

Идеального не существует в природе априори lol . Стремится надо  lol  Что и делаем  lol . Примеров в сети вагон, и тоже с кучей недостатков. Что же придется сесть с другими авторами и  икать lol. NoName, я не против если Вы предложите более совершенный и простой понятный алгоритм, даже приму участие lol .

Неактивний

#12 2016-03-03 13:43:41

NoName
Customer
З Київ
Зареєстрований: 2014-07-08
Повідомлень: 1,446

Re: помогите новичку пожалуйста !

https://www.arduino.cc/en/Tutorial/SerialEvent
пойдем по более привычному пути
условие,  у запроса footer = '\n'

change #5

/*
  Serial Event example

 When new serial data arrives, this sketch adds it to a String.
 When a newline is received, the loop prints the string and
 clears it.

 A good test for this is to try it with a GPS receiver
 that sends out NMEA 0183 sentences.

 Created 9 May 2011
 by Tom Igoe

 This example code is in the public domain.

 http://www.arduino.cc/en/Tutorial/SerialEvent

 */
#define max_length 200

String inputString = "";         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete
boolean string_error = false;  // whether the string is overflow


void setup() {
  // initialize serial:
  Serial.begin(9600);
  // reserve 200 bytes for the inputString:
  inputString.reserve(max_length);
}

void loop() {
  // print the string when a newline arrives:
  if (stringComplete) {
// change #5 Serial.println("R1"); 
    if (inputString == "Rele 1")  {  Serial.println("R1");  digitalWrite(led11, HIGH); }
    else if (inputString == "Rele 2") {  Serial.println("R2"); digitalWrite(led12, HIGH); }
    else if (inputString == "Rele 3") {  Serial.println("R3"); digitalWrite(led13, HIGH); }
   // add change #3 
   else     {
     Serial.print("err: ");
     Serial.println(inputString);
          }
// clear the string:
    inputString = "";
    stringComplete = false;
  }
else if ( string_error == true )
{
   // while (1);   achtung!!!!  wtf?
    string_error = false;
    // clear the string:
    inputString = "";
    stringComplete = false;
    // но я бы сделал анализ по циклическому буферу от последнего байта :) 
    // забил бы на  achtung), и отказался бы от стринга,   ибо непривычно ) 
}

}

/*
  SerialEvent occurs whenever a new data comes in the
 hardware serial RX.  This routine is run between each
 time loop() runs, so using delay inside loop can delay
 response.  Multiple bytes of data may be available.
 */
void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the inputString:
   // add change #4 
  if (inChar >= 0x20 )
  { 
   inputString += inChar;
  }
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') {
      stringComplete = true;
    }
  else
if ( inputString.length()  >= (max_length-1)) 
   { string_error = true; }
  }
}

кто проверит?, ЭТО работает или нет? )

Остання редакція NoName (2016-03-03 17:44:59)

Неактивний

#13 2016-03-03 15:06:49

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: помогите новичку пожалуйста !

Неа...не компилится. Компилятор ругается на if ( strlen (inputString) >= max_length  ) такими матюками er:57: error: cannot convert 'String' to 'const char*' for argument '1' to 'size_t strlen(const char*)'
cannot convert 'String' to 'const char*' for argument '1' to 'size_t strlen(const char*)'

Неактивний

#14 2016-03-03 15:15:14

NoName
Customer
З Київ
Зареєстрований: 2014-07-08
Повідомлень: 1,446

Re: помогите новичку пожалуйста !

логично,  но мало ли , я ж не знаю насколько он strict ) а то вольностей пообещали )
помогайте ) нужно вместо strlen  ( да и header не включил я) )  функция определения длины строки
заменить на местное для работы со стрингом 
inputString.length есть такое?
if ( inputString.length  >= max_length  )
ладно вечером почитаем )
и вместо сравнения нужно compare сделать


add
заменить на
if ( inputString.length()  >= (max_length-1)) 
// скушаем 1 байт от буфера )

Остання редакція NoName (2016-03-03 15:18:25)

Неактивний

#15 2016-03-03 15:15:27

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: помогите новичку пожалуйста !

Да. Забыл. Кавычку одинарную уберите в if (inputString == "Rele 2"') digitalWrite(led12, HIGH); Копи паст не дремлет  big_smile .

Неактивний

#16 2016-03-03 15:57:39

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: помогите новичку пожалуйста !

Думаю надо:
   if ( inputString.length() >= max_length  )
   { string_error = true; }

Неактивний

#17 2016-03-03 16:04:30

NoName
Customer
З Київ
Зареєстрований: 2014-07-08
Повідомлень: 1,446

Re: помогите новичку пожалуйста !

Nefreemen, самое смешное что ardnew уже получил что нужно и тему не читает )

Неактивний

#18 2016-03-03 16:17:56

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: помогите новичку пожалуйста !

Угу.  big_smile  Я тут ставлю Гипертерминал на 10 пытаюсь проверить. Не работает зараза, в inputString то что ввел через терминал, а оно зараза не работает ( а должно ) roll и тут открываю глаза...Мама моя... я долблю ему "Relay 1" надо "Rele 1" lol Но все равно что то не так. К стати я не вычитал конечный байт...Может из за этого.

Неактивний

#19 2016-03-03 16:27:21

NoName
Customer
З Київ
Зареєстрований: 2014-07-08
Повідомлень: 1,446

Re: помогите новичку пожалуйста !

нет, гипертерминал отправляет \r\n
и строки не равны, нужно не equ  ( == ) делать а сравнение по содержимому, я еще не читал что доступно для стринга в ардуино (
эхо принятой строки отправляйте обратно )

add change #3

Остання редакція NoName (2016-03-03 16:31:35)

Неактивний

#20 2016-03-03 16:31:18

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: помогите новичку пожалуйста !

void loop() {
  // print the string when a newline arrives:
  if (stringComplete) {
   
    Тут inputString все Ок, а дальше в if не работает.

    if (inputString == "Rele 1") digitalWrite(led11, HIGH);
    if (inputString == "Rele 2") digitalWrite(led12, HIGH);

Неактивний

#21 2016-03-03 16:34:32

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: помогите новичку пожалуйста !

Вот именно так и делаю- обратно в Serial отправляю inputString, получаю то что отправил.

Неактивний

#22 2016-03-03 16:36:28

NoName
Customer
З Київ
Зареєстрований: 2014-07-08
Повідомлень: 1,446

Re: помогите новичку пожалуйста !

if (inChar >= 0x20 )
  {
   inputString += inChar;
  }
убрал спец символы

Неактивний

#23 2016-03-03 17:38:33

ardnew
Учасник
Зареєстрований: 2016-03-02
Повідомлень: 62

Re: помогите новичку пожалуйста !

NoName пише:

Nefreemen, самое смешное что ardnew уже получил что нужно и тему не читает )

читаю, и очень внимательно !
и получил как бы не совсем то, вернее то, но реле как то включаются через раз
какую либо статистику не собрать sad

и еще, никак не могу сообразить, у меня 8 реле, нужно сделать так что бы по сигналу включалось только одно реле, а остальные выключались,
например, пришел сигнал "Rele 2" включилось реле 2, пришел сигнал "Rele 5" включилось бы реле 5, а реле 2 выключилось,
короче, всегда может быть включено только одно реле из восьми.

Остання редакція ardnew (2016-03-03 17:49:36)

Неактивний

#24 2016-03-03 17:43:26

NoName
Customer
З Київ
Зареєстрований: 2014-07-08
Повідомлень: 1,446

Re: помогите новичку пожалуйста !

это просто см change 5
добавлен лог выполнения

Остання редакція NoName (2016-03-03 17:45:27)

Неактивний

#25 2016-03-03 18:24:50

ardnew
Учасник
Зареєстрований: 2016-03-02
Повідомлень: 62

Re: помогите новичку пожалуйста !

NoName пише:

это просто см change 5
добавлен лог выполнения

если правильно понял..

вот это работает четко if (x == 1) digitalWrite(led11, HIGH);
если с терминала даю один байт, типа 1, 2, или 3, но у меня текстовая строка, и вот в этом вся проблема  sad

Неактивний

Швидке повідомлення

Введіть повідомлення і натисніть Надіслати

Підвал форуму