Помогите найти ошибку в алгоритме

Drew20
Offline
Зарегистрирован: 09.02.2018

Всем добрый день или вечер. Возникла проблема с написанием скетча для Ардуино. На данный момент я использую Arduino UNO и Bluetooth HC-06. У меня не получается разделить входной поток информации на определенные переменные. Вообще от микроконтроллера требуется что бы он давал возможность выбрать цвет и дальше он принимает время задержки с смартфона. Сейчас с данным скетчем у меня при выборе цвета зажигается нужный цвет но дальше если я посылаю время задержки то светодиод тухнет и не подает признаков жизни. Если кто-нибудь знает как решить данную проблему или видел подобные проекты буду очень благодарен за любую оказанную помощь.

const int rPin = 3;
const int gPin = 5;
const int bPin = 6;
int chosed_color;
int val;  
int color;

void setup() 
{
  Serial.begin(9600);
  pinMode( rPin, OUTPUT );
  pinMode( gPin, OUTPUT );
  pinMode( bPin, OUTPUT );
  
}

void loop() 
{
  while(Serial.available()>0)
  {
     color = Serial.read();
   if(color==1)
      {
       chosed_color = rPin;
      digitalWrite( rPin, HIGH );       
      digitalWrite(rPin, LOW);  
       return chosed_color;
      }
        else if(color==2)
      {
       chosed_color = bPin;
       digitalWrite( bPin, HIGH );     
      digitalWrite(bPin, LOW);  
       return chosed_color;
      }
         else if(color==3)
      {
        chosed_color = gPin;
       digitalWrite( gPin, HIGH );
       digitalWrite(gPin, LOW);  
       return chosed_color;
      }
  }
if(Serial.available()>0) 
{
  val = Serial.read();
}

      digitalWrite( chosed_color, HIGH );
      delay(val);       
      digitalWrite(chosed_color, LOW);  
      delay(val); 
}

 

vk007
Offline
Зарегистрирован: 16.06.2015

Чето непонятен смысл этого всего. Как оно должно все это работать? Насколько я понял, ждать со смартфона сначала цвет, потом ждать задержку, и, если данные все получены, мигнуть указанным светодиодом с указаной задержкой? Так?

Ну и, что вы вкладываете в смысл return chosed_color;? Кому вы возвращаете chosed_color?

b707
Offline
Зарегистрирован: 26.05.2017

Drew20,  у вас прием цвета и прием задержки написан одинаково - каким образом микроконтроллер должен их различить? Вам нужно придумать разные команды на изменение цвета и на задержку, например добавив для цвета в начале букву "с" - "с1" - это будет означать "цвет = 1". И аналогично для задержек, например "d250"  = "задержка 250мс"

Drew20
Offline
Зарегистрирован: 09.02.2018

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

vk007 пишет:

Чето непонятен смысл этого всего. Как оно должно все это работать? Насколько я понял, ждать со смартфона сначала цвет, потом ждать задержку, и, если данные все получены, мигнуть указанным светодиодом с указаной задержкой? Так?

Ну и, что вы вкладываете в смысл return chosed_color;? Кому вы возвращаете chosed_color?

vk007
Offline
Зарегистрирован: 16.06.2015

Drew20 пишет:

да вы все правильно поняли, но светодиод должен моргать бесконечно

ОК, продолжим. Что должен делать светодиод до того, как он получит данные? И второе, в процессе "бесконечного моргания" программа должна все так же ждать данные или приняли один раз и "до свидания"?

__Alexander
Offline
Зарегистрирован: 24.10.2012

return в середине функции loop никого не беспокоит?

vk007
Offline
Зарегистрирован: 16.06.2015

__Alexander пишет:

return в середине функции loop никого не беспокоит?

Я уже писал об этом. Но это не важно, там вообще код неправильно построен, поэтому надо перепысывать. Пока добиваюсь от ТС полного описания, как должно все работать.

Drew20
Offline
Зарегистрирован: 09.02.2018

мне необходимо выбирать цвет светодиода и дальше им мигать неопределенное время, так-же светодиод доолжен изменять частоту своего мигания на лету тоесть безпрерывно принимать частоту своего моргания определенным цветом. Я согласен со всеми вами что мой код имеет много ошибок или вообще не правильный, у меня только начальные знания в области програмирования и мой скетч может содержать КУЧУ ошибок. return я вставил только потому что у меня уже иссякли идеи как решить поставленную задачу. Я могу на данный момент отдельно выполнять только такие задачи как, изменение частоты мигания определенного цвета или просто выбрать определенный цвет и все. Если кто знает как мне помочь буду очень благодарен

vk007 пишет:

__Alexander пишет:

return в середине функции loop никого не беспокоит?

Я уже писал об этом. Но это не важно, там вообще код неправильно построен, поэтому надо перепысывать. Пока добиваюсь от ТС полного описания, как должно все работать.

vk007
Offline
Зарегистрирован: 16.06.2015

Тогда все просто и я бы предложил организовать все так. В сетапе нужно читать цвет светодиода (ведь я правильно понял, что цвет выбирается только один раз?). А уже в лупе читать задержки и мигать выбранным светодиодом.

Drew20
Offline
Зарегистрирован: 09.02.2018
const int rPin = 3;
const int gPin = 5;
const int bPin = 6;
int pins[3] = {rPin, gPin, bPin};
int chosed_color;
int color;
int val;  

void setup() 
{
  Serial.begin(9600);
  pinMode( rPin, OUTPUT );
  pinMode( gPin, OUTPUT );
  pinMode( bPin, OUTPUT );
   if(Serial.available()>0) 
{
color = Serial.read();
  chosed_color = pins[color-1];
}
  
}

void loop() 
{
    if(Serial.available()>0) 
{
  val = Serial.read();
}
digitalWrite( chosed_color, HIGH );
  delay(val);       
  digitalWrite(chosed_color, LOW);  
  delay(val); 
  }

я вот так попробовал но не получается может опять где-то ошибка???

vk007 пишет:

Тогда все просто и я бы предложил организовать все так. В сетапе нужно читать цвет светодиода (ведь я правильно понял, что цвет выбирается только один раз?). А уже в лупе читать задержки и мигать выбранным светодиодом.

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015
void setup() 
{
  Serial.begin(9600);
  pinMode( rPin, OUTPUT );
  pinMode( gPin, OUTPUT );
  pinMode( bPin, OUTPUT );
  chosed_color = -1;
  while(chosed_color == -1)
  {
    if(Serial.available()>0) 
    {
      color = Serial.read();
      chosed_color = pins[color-1];
    }
  }
}

 

Drew20
Offline
Зарегистрирован: 09.02.2018

а почему там в блоке while chosed_color==-1?????

Penni пишет:

void setup() 
{
  Serial.begin(9600);
  pinMode( rPin, OUTPUT );
  pinMode( gPin, OUTPUT );
  pinMode( bPin, OUTPUT );
  chosed_color = -1;
  while(chosed_color == -1)
  {
    if(Serial.available()>0) 
    {
      color = Serial.read();
      chosed_color = pins[color-1];
    }
  }
}

 

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Вам надо в сетапе дождаться получения цвета. Поэтому задаем -1 т.к. пина с таким номером быть не может и крутимся в цикле пока пользователь не хзадал цвет и chosed_color не стал отличным от -1. Вообще это все в лупе можно делать, но раз vk007 предлагал в сетапе я и кинул вариант для сетапа.

vk007
Offline
Зарегистрирован: 16.06.2015

Drew20 пишет:

а почему там в блоке while chosed_color==-1?????

Это значит, что будем крутиться в цикле пока chosed_color не присвоится какое-то значение.

Но я в таком случае chosed_color лучше бы проверял на допустимое значение (т.е. в данном случае 1, 2 или 3).

И кстати, читать лучше через Serial.parseInt() - если данные вводятся в порт вручную, то так сразу получим число, а не коды вводимых цифр.

Drew20
Offline
Зарегистрирован: 09.02.2018

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

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Можно, во втором посте Вам написали как это сделать

vk007
Offline
Зарегистрирован: 16.06.2015

Drew20 пишет:

а можно непрерывно считывать цвета светодиода

Да, можно, и даже уже ответили как. От себя добавлю. Понятно, что определение цвета делать в таком случае не в сетапе, а уже в лупе. Чтобы было проще можно все передавать одной коммандой. Например, "R250", или "G100", или "B300". Первый символ - цвет, остальное - задержка. Принимаем из serial строку и анализируем ее.

Drew20
Offline
Зарегистрирован: 09.02.2018

та я то этот пост читал, но мне не понятно что мы должны слать через блютуз и как нам инициализировать его дальше? и как его потом использовать для дальнейшей работы. тоесть мы например получаем с телефона d250  это значит что частота моргания светодиода 250 дальше мы знаем что изменить частоту светодиода можно через delay(???) и куда нужно слать полученную частоту. просто на сериал подается не byte а int и соответственно у нас есть два числа одно отвечает за цвет а второе за частоту. я могу слать данные при нажатии на кнопку к которой привязана определенная функция(android) а не считывать строку

vk007
Offline
Зарегистрирован: 16.06.2015

Drew20 пишет:

мне не понятно что мы должны слать через блютуз и как нам инициализировать его дальше?

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

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

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

Drew20
Offline
Зарегистрирован: 09.02.2018

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

Drew20
Offline
Зарегистрирован: 09.02.2018

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

vk007
Offline
Зарегистрирован: 16.06.2015

ОК, т.е.: 1) передаем цвет и частоту, я правильно понял? 2) Цвета три - R, G, и B? 3) Гасить светодиоды надо? 4) Какой диапазон частоты нужен? 5) Значение частоты любое или набор фиксированных значений? 6) В один момент времени мигает только один светодиод?

Drew20
Offline
Зарегистрирован: 09.02.2018

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

vk007
Offline
Зарегистрирован: 16.06.2015

Drew20 пишет:

диапазон частот вообще настроен на телефоне но если это нужно то мигает от 0 до 200 но лично мне легче когда у могу в программе на андроид сам поменять при необходимости крайние значения, значение частот любое

1) от 0 до 200 - это в каких попугаях?

2) всему есть свои пределы, с минимумом и максимумом все-таки надо определиться.

b707
Offline
Зарегистрирован: 26.05.2017

vk007 пишет:

2) всему есть свои пределы, с минимумом и максимумом все-таки надо определиться.

после прочтения сообщения выше я бы написал: "Всему есть предел - нельзя же так наплевательски обращаться с предложениями и знаками препинания!"

Каждый программист - в каком-то смысле писатель :) Человек, не умеющий связно выражать мысли - вряд ли сможет написать хорошую программу.

Drew20
Offline
Зарегистрирован: 09.02.2018

насколько я понял то частота в ардуино измеряется в милисекундах, а предели максимум от 0 до 1000

vk007 пишет:

Drew20 пишет:

диапазон частот вообще настроен на телефоне но если это нужно то мигает от 0 до 200 но лично мне легче когда у могу в программе на андроид сам поменять при необходимости крайние значения, значение частот любое

1) от 0 до 200 - это в каких попугаях?

2) всему есть свои пределы, с минимумом и максимумом все-таки надо определиться.

vk007
Offline
Зарегистрирован: 16.06.2015

Drew20 пишет:

насколько я понял то частота в ардуино измеряется в милисекундах, а предели максимум от 0 до 1000

Ага, т.е. все-таки не частота, а задержка (фактически полупериод)? Частота сигнала и его период - это несколько разные вещи, с точностью до наоборот.

Drew20
Offline
Зарегистрирован: 09.02.2018

ну эти данные отправляються в функцию delay() так что наверное да это задержка

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Drew20 пишет:

насколько я понял то частота в ардуино измеряется в милисекундах

Частота измеряется в Герцах.

vk007
Offline
Зарегистрирован: 16.06.2015

Тогда я бы предложил такой формат: буквой передаем цвет (возможные варианты комманды R, G и B), а числом - задержку (0 - 1000).

В таком случае для определения отправленной комманды в скетче я бы делал так: в if(Serial.available()>0) первый байт сначала прочитал через Serial.peek() (эта функция читает символ из буфера, но не удаляет его оттуда). Если прочиталась не цифра, а буква ('R', 'G' или 'B'), значит это комманда смены цвета и переключаем активный светодиод. (После этого с помощью Serial.read() надо все-таки вычитать этот символ из буфера (в никуда), чтобы он оттуда удалился). Если же в результате чтения Serial.peek() выдал цифру, значит пришла комманда смены задержки. Принимаем ее с помощью Serial.parseInt() и полученное число используем в delay. Единственный нюанс, комманды надо передавать не числом, а строкой (например, "250" - т.е. три символа подряд: '2', '5' и '0').

Drew20
Offline
Зарегистрирован: 09.02.2018

ну задержка, я уже знаю эти тонкости, просто тогда немного тупанул

 

Drew20
Offline
Зарегистрирован: 09.02.2018

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

 

vk007
Offline
Зарегистрирован: 16.06.2015

Ну как-бы там того скетча кот наплакал, что менять, что переписывать - один хер.

Данные как передаются? Пока через монитор порта или на смартфоне уже есть готовая программа?

b707
Offline
Зарегистрирован: 26.05.2017

Drew20 пишет:

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

 

да ничего у вас не хорошо. Весь код из ошибок. Вы сейчас задержку как отправляете? - в виде  int ? - а читаете только один байт. То есть больше 256 вообще передать не можете.  Это не говоря о том, что она вообще из сериала не читается. Ваш код не рабочий в принципе. его только выкинуть.

Drew20
Offline
Зарегистрирован: 09.02.2018

ну почему-же я пробовал отправлять больше 256 и нормально работало, просто нужно немного доделать и будет нормально

vk007
Offline
Зарегистрирован: 16.06.2015

Поверьте, в данном случае лучше написать с нуля. Тем более, что там писать почти нечего, и примерную последовательность обработки я уже написал.

b707
Offline
Зарегистрирован: 26.05.2017

Drew20 пишет:

ну почему-же я пробовал отправлять больше 256 и нормально работало

совершенно ответственно заявляю. что это ВРАНЬЕ. Вы читаете задержку из порта как

val = Serial.read();

В этом случае у вас читается из порта байт, и в нем НИКАК НЕ МОЖЕТ БЫТЬ больше 256.

Drew20
Offline
Зарегистрирован: 09.02.2018

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

vk007 пишет:

Поверьте, в данном случае лучше написать с нуля. Тем более, что там писать почти нечего, и примерную последовательность обработки я уже написал.

Drew20
Offline
Зарегистрирован: 09.02.2018

но я посылаю int у меня есть переменная int которой присваеваеться это значение как там байт береться я не пойму

 

b707 пишет:

Drew20 пишет:

ну почему-же я пробовал отправлять больше 256 и нормально работало

совершенно ответственно заявляю. что это ВРАНЬЕ. Вы читаете задержку из порта как

val = Serial.read();

В этом случае у вас читается из порта байт, и в нем НИКАК НЕ МОЖЕТ БЫТЬ больше 256.

b707
Offline
Зарегистрирован: 26.05.2017

Drew20 пишет:

но я посылаю int у меня есть переменная int которой присваеваеться это значение как там байт береться я не пойму

 

не имеет ни малейшего значения, что вы посылаете. Посылаете вы может и правильно, а вот читаете - нет. Оператор Serial.read() читает из порта ОДИН БАЙТ  - понимаете? он не может прочитать ни int ни long - хоть вы ему все собрание сочинений Ленина пошлите разом.

Drew20
Offline
Зарегистрирован: 09.02.2018

и как мне тогда читать?? int я так понял мы не прочитаем никак?

b707 пишет:

Drew20 пишет:

но я посылаю int у меня есть переменная int которой присваеваеться это значение как там байт береться я не пойму

 

не имеет ни малейшего значения, что вы посылаете. Посылаете вы может и правильно, а вот читаете - нет. Оператор Serial.read() читает из порта ОДИН БАЙТ  - понимаете? он не может прочитать ни int ни long - хоть вы ему все собрание сочинений Ленина пошлите разом.

b707
Offline
Зарегистрирован: 26.05.2017

Drew20 пишет:

и как мне тогда читать?? int я так понял мы не прочитаем никак?

командой read за один раз - никак. Можно либо передавать в виде строк, как советует VK007, можно в виде двоичных данных - цепочек байт, но в любом случае данные придется собирать из отдельных байт и анализировать. Нужно знать, где начало сообщения и где конец и какова его длина.

То, что вам выше написал vk007 - это самый упрощенный вариант обмена по сериал, проще просто не бывает.

vk007
Offline
Зарегистрирован: 16.06.2015

Вы не ответили, что у вас за программа стоит на смартфоне? Самописная? Если будете делать по моей методике, не забудьте "научить" ее отправлять не числа в виде int, а строки в виде символов. Т.е. символы ('R', 'G' или 'B') для цвета и строки в виде отдельных символов цифр ('0'-'9') для чисел для задержки - "0", "99", "250", ..., "1000". Иначе вся эта затея выеденного яйца не будет стоить, например, если отправить в порт число 82 - как его следует понимать, как цвет (символ 'R') или задержку равную 82?

b707
Offline
Зарегистрирован: 26.05.2017

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

Drew20
Offline
Зарегистрирован: 09.02.2018

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

 

Drew20
Offline
Зарегистрирован: 09.02.2018

спасибо за совет b707 обязательно прочту мне это пригодится в дальнейших проектах

vk007
Offline
Зарегистрирован: 16.06.2015

Если своя, то это ОК, можно напрограмить что хош. Но пока можно обойтись и без смартфона, а лучше экспериментировать в мониторе порта на ПК. Отладите так, потом и за смартфон браться можно будет.

Drew20
Offline
Зарегистрирован: 09.02.2018

ну я сейчас пробую сделать то что вы сказали но не сильно получается через монитор порта, я так понял что там отправить можно только строку у которой расширение byte и проблема опять с скетчем он вообще не работает, вот я в луп сделал считывание всего что нужно, но оно не читает ничего, походу где-то опять ошибка, мне вот не понятно ваша строка "если прочиталась не цифра, а буква ('R', 'G' или 'B'), значит это комманда смены цвета и переключаем активный светодиод. (После этого с помощью Serial.read() надо все-таки вычитать этот символ из буфера (в никуда), чтобы он оттуда удалился). Если же в результате чтения Serial.peek() выдал цифру, значит пришла комманда смены задержки. " что означает вычитать символ из буфера, что бы он оттуда удалился, и как я потом смогу менять частоту мигания светодиода если он еще не зажегся сначала ведь нужно выбрать цвет а потом уже меня частоту

void loop() 
{
    if(Serial.available()>0) 
    {
      color = Serial.peek();
      chosed_color = pins[color-1];
      val = Serial.read();
    }
digitalWrite( chosed_color, HIGH );
  delay(val);       
  digitalWrite(chosed_color, LOW);  
  delay(val); 
  }

 

b707
Offline
Зарегистрирован: 26.05.2017

Drew20, начните все-таки с учебника, и даже не с учебника Си. а "ПК для чайников" - почитайте что такое байты и чем они отличаются от символов.

Ну, право, то, что вы делаете - это браться решать диффуравнения, не выучив таблицу умножения. Я на таком уровне помогать не берусь. Может vk007 согласится, в таком случае от души ему сочувствую, это будет непросто.

vk007
Offline
Зарегистрирован: 16.06.2015

Вот вы прочитали color = Serial.peek(); но не делаете анализ того, что прочитали, а сразу его используете для выбора цвета.

А надо проверить, если color == 'R' (или 'G', или 'B') значит это цвет и тогда уже chosed_color = pins[color-1]; а следом Serial.read(); (для удаления этой буквы из буфера).

Если же color == '0' (или '1', или '2', ..., или '9'), т.е. считали цифру, то значит в порт пришло число (т.е. данные для задержки) и читаем его val = Serial.parseInt();

 

b707
Offline
Зарегистрирован: 26.05.2017

vk007 . да о чем вы???

вы вчитайтесь - он в порт "строку с расширением byte" отправляет :))))))