Управление цветом фона через serial

superaft
Offline
Зарегистрирован: 13.02.2015

Доброго времени суток! К Arduino Uno подключены 3 потенциометра, при повороте одного из них должен менятся цвет фона. То есть при повороте первого потенциометра должно изменяться значение красного, второго - значение зеленог, третьего - знаяение синего. Помогите пожалуйств реализовать такуя штуку. Заранее спасибо!

ourlive
Offline
Зарегистрирован: 26.05.2012

Три байта данных (r;g;b) просто в терминал уже успешно передаются?

superaft
Offline
Зарегистрирован: 13.02.2015

В терминал значения передаются через запятую в таком виде: 255,255,0 (r,g,b).
Или надо отправлть в другом виде? Можно подробнее о этом рачказать, просто в врдуино новичок.
Скетч выложу позднее добавлю коменатарии и имена пернменных для удобства изменю.

ourlive
Offline
Зарегистрирован: 26.05.2012

Скетч нужен будет когда оно неверно работать будет, а пока теория.

Сейчас данные передаются в виде отдельных строк (каждый пакет в новой строке) разделённые запятыми, так?

В терминале всё красиво, понятно и однозначно.

Процессинг уже способен принять эти строки (см. стандартный пример) и например напечатать их?

superaft
Offline
Зарегистрирован: 13.02.2015

Не пойму вас, мне нужно заставить процесинг обрабатывать эти строки

ourlive
Offline
Зарегистрирован: 26.05.2012

Что бы их обрабатывать, их нужно сначала корректно принять. Ладно, допустим процессинг принял строку "200,200,150", очевидно, что нужно разбить имеющуюся строку на три с 1го символа длиной 3, с 5го и т.д. полученные три строчные переменные преобразовать в int и всё. 1, 2 - ссылки по теме. Вобщем то, что вам нужно в примере описания второй функции.

superaft
Offline
Зарегистрирован: 13.02.2015

Написал скетч программа запустиась, пока не использовал Serial.

Значение цвета устанавливал программно 255,255,255 (белый),  но в окне программы вместо белого серый цвет

Вот скетч если нужен:

import processing.serial.*;

Serial myPort;


String Read = "255,255,255"; // Программно укаываем значения RGB
float[] colors = float (split (Read, ','));

void setup()
{
  size (500,500);
}

void Draw()
{    
     background (colors[0], colors[1], colors[2]);  
}

 

superaft
Offline
Зарегистрирован: 13.02.2015

Разобрался в чем была ошибка, все начало работать нормально.

Написал скетч с использованием Serial:

import processing.serial.*;

Serial myPort;

void setup()
{
   myPort = new Serial(this, "COM3", 9600);
  size (500,500);
}

void draw()
{ 
  while (myPort.available() > 0)
  {
    String Read = myPort.readString();
    float[] nums = float(split(Read, ','));
    
    background (nums[0], nums[1], nums[2]);
  }  
}  

Программа запускается но сразу зависает и вылетает, думаю не правильно принял данные, помогите.

ourlive
Offline
Зарегистрирован: 26.05.2012

com3 скорее всего занят или не существует

println(Serial.list());

в помощ, и 

println(Read);

после чтения тоже.

ourlive
Offline
Зарегистрирован: 26.05.2012

а ещё параметры rgb - int, а не float

superaft
Offline
Зарегистрирован: 13.02.2015

То есть нужно параметры rgb перевести в int а не float?

С ком портом все впорядке фон меняется если перед запуском изменить положения потенциометро.

Про println(Read); расскажите подпобнее, не совсем пойму как его использовать.

ourlive
Offline
Зарегистрирован: 26.05.2012

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

String Read = myPort.readString();
println(Read);

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

Короче, нужно видеть что причитано. И проверять данные на правильность. Наприменр строка короче 5-ти символов точно битая, строка не имеющая двух разделительных запятых не корректна и т.п.

superaft
Offline
Зарегистрирован: 13.02.2015

То есть нужно отфильтровывать принятые данные пока не прийдет нормальное значение?

К примеру если процесинг принял какую-то бяку, допустим 255,255,55255,255,255 вместо 255,255,255 то проверять до тех пор пока не получить 255,255,255?

Вот скрин буфера с кучей бяк:

И в мониторе порта ArduinoIDE в начале тоже вылазит бяка:

 
ourlive
Offline
Зарегистрирован: 26.05.2012

Если почитать описание функции которой вы читаете данные, то выяснится, что она читает все данные из буфера, которые там есть, или один символ или 20.. Как повезет. Проще всего читать по одному символу, ваша строка заканчивается asc символом с кодом 13 (новая строка). Символы стоит складывать в строку. А уже полученную строку обрабатывать.

ourlive
Offline
Зарегистрирован: 26.05.2012

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

superaft
Offline
Зарегистрирован: 13.02.2015

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

ourlive
Offline
Зарегистрирован: 26.05.2012

посимвольный приём

String bufer="";   

while (myPort.available() > 0) {
    char inByte = myPort.readChar(); // прочитать символ с порта
    if (inByte==char(13)) {   // после прочтения символа начала строки: char(13)
           
    // группа событий после получения данных
      
    bufer=""; } // сбросить буфер
    else {
    bufer=bufer+inByte; //складывать символы в буфер 
    } 
}  

 

для создания одной длины строки, если переменная имеет значение "1", то в порт с ардуины отправлять "00"+"1" соответственно, элементарно же

 

superaft
Offline
Зарегистрирован: 13.02.2015

Что-то совсем ничего не понимаю, может попробовать спопсоб проще, не отпровлять значения через запятую а сразу отправлять hex значение всего цвета в таком виде: #FFFFFF (белый цвет), проблема в том что строка всегда должна быть равна 7-ми символам (вместе с решеткой).

superaft
Offline
Зарегистрирован: 13.02.2015

Не понятно что значит переменная bufer =  ""  и как она сбрасывает буфер ? 

Значения цветов нужно считывать с буфера? распишите все более подробно.

И как сделать стргку ожной длиный так же расккжите подробней

ourlive
Offline
Зарегистрирован: 26.05.2012

Переменная bufet простая строчная переменная, в нее идёт накопление символов прочитанных с порта, накопление идёт до момента чтения символа chr(13) "новая строка", после чего данные из переменной отправляются на обработку/преобразование и т.п., а сама переменная обнуляется bufer=""; И всё сначала, новое накопление прочтённых символов и т.д. Объявлять:

String bufer="";

нужно как глобальную само собой.

superaft
Offline
Зарегистрирован: 13.02.2015

Добавил в скетч :

import processing.serial.*;

String bufer="";

Serial myPort;

void setup()
{
   myPort = new Serial(this, "COM3", 9600);
  size (500,500);
}

void draw()
{ 
  while (myPort.available() > 0)
  {
    char inByte = myPort.readChar();
    
    if (inByte==char(13)) {
     bufer=""; }
    else{bufer=bufer+inByte;}
    
    println(bufer);
    
    
      //int[] nums = int(split(bufer, ','));
     // 
      //background (nums[0], nums[1], nums[2]);
  }  
}  

Теперь такого шлака нет но в буфер выводится по одному символу вот серин:

Дальше начинается все заново.

ourlive
Offline
Зарегистрирован: 26.05.2012

Строку 23 вставить между 19 и 20ой, а потом думать.

superaft
Offline
Зарегистрирован: 13.02.2015

Тепрь буфер пустой

 

superaft
Offline
Зарегистрирован: 13.02.2015

А нет, видмо процесинг глюкнул 

Скрин буфера:

ourlive
Offline
Зарегистрирован: 26.05.2012

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

superaft
Offline
Зарегистрирован: 13.02.2015

Да, но как теперь обработать эти значения? 

Если раскоментировать 


      //int[] nums = int(split(bufer, ','));
     // 
      //background (nums[0], nums[1], nums[2]);

То проблема все равно не исчезает процесинг все равно вылетает и ругается на масивы

 

ourlive
Offline
Зарегистрирован: 26.05.2012

Это вот работает?


String bufer="10,10,255"; 

void setup()
{
  size (500,500);
  int[] nums = int(split(bufer, ','));
  background (nums[0], nums[1], nums[2]);
}

void Draw()
{    
      
}

 

superaft
Offline
Зарегистрирован: 13.02.2015

Да это работает

ourlive
Offline
Зарегистрирован: 26.05.2012

Ну значит начинается самое увлекательное, найти ошибку и победить её. Тык в помощь. Ну и печатать в терминал всё что только можно, все переменные. Косяк наверняка в том, что приходит что нибудь типа "255,255" в буфер, и blue оказывается не определено.

superaft
Offline
Зарегистрирован: 13.02.2015

А нет рессурса где про это можно прочитать на русском, на английском не могу перевести 

superaft
Offline
Зарегистрирован: 13.02.2015

И как его использовать в моем коде ?

superaft
Offline
Зарегистрирован: 13.02.2015

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

ourlive
Offline
Зарегистрирован: 26.05.2012

Если сообщение не соответствует шаблону "###,###,###", то пропустить эту строку и ждать следующую. Останавливать программу из-за одного битого пакета резона нет.

superaft
Offline
Зарегистрирован: 13.02.2015

Я правильно пытаюсь добавить это в скетч?

И объясните что писать в catch()

Скетч:

import processing.serial.*;

String bufer="";
String line;

Serial myPort;

void setup()
{
   myPort = new Serial(this, "COM4", 9600);
  size (500,500);
}

void draw()
{ 
  while (myPort.available() > 0)
  {
    try{
      line = myPort.readString();
    }catch (не понятно что здесь писать){
      bufer=""
    }
    
    char inByte = myPort.readChar();
    
    if (inByte==char(13)) {
    println(bufer);
     bufer=""; }
    else{bufer=bufer+inByte;}
    

    
    
      //int[] nums = int(split(bufer, ','));
   
      //background (nums[0], nums[1], nums[2]);
  }  
}  

 

superaft
Offline
Зарегистрирован: 13.02.2015

Я так понимаю в catch нужно в catch нужно () нужно прописать что-то типа если не равно шаблону "###,###,###" но, как указать чт==неравенство и как задать шаблон?

ourlive
Offline
Зарегистрирован: 26.05.2012

Ну блин, а описание по функции хотя бы гуглом перевести? try/ catch это перехват критических ошибок функции. Когда случается "аяяй, критическая ошибка выполнения в функции", эта структура позволяет не прерывать выполнение скетча, а например выдать сообщение об этом или изменить значения каких то переменных. Например 


try{
      line = myPort.readString();
 }catch {  println("че то данные не читаются, к чему бы это?");  }

 

 

superaft
Offline
Зарегистрирован: 13.02.2015

Я как раз гуглом и переводил))))

Засунул в  скетч:

//String bufer="";
String line;

Serial myPort;

void setup()
{
   myPort = new Serial(this, "COM4", 9600);
  size (500,500);
}

void draw()
{ 
  while (myPort.available() > 0)
  {
   
try{
      line = myPort.readString();
 }catch {  println("error");  }
    
   // char inByte = myPort.readChar();
    
   // if (inByte==char(13)) {
   // println(bufer);
    // bufer=""; }
   // else{bufer=bufer+inByte;}
    

    
    
      //int[] nums = int(split(bufer, ','));
   
      //background (nums[0], nums[1], nums[2]);
  }  
}  

Не запускается выдает ошибку expecting LAREN, found '{'

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

del

superaft
Offline
Зарегистрирован: 13.02.2015

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

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

В общем, я выше ошибся. Оказалось, что у Вас неправильный синтаксис catch - https://processing.org/reference/catch.html

superaft
Offline
Зарегистрирован: 13.02.2015

Я так понимаю после catch нужно в скобках указать исключение?

superaft
Offline
Зарегистрирован: 13.02.2015

Какая именно ошибка? Если выше ябыл прав, то как мне его впихнуть в мой код?