Переменные

stupiddev
Offline
Зарегистрирован: 26.11.2019

Всем привет. Есть небольшой вопрос. В общем у меня есть скетч ардуино, и есть приложение на питоне(gui) для работы с com-портом ардуины. Так вот вопрос в том, можно ли через этот же интерфейс на питоне, по нажатию на кнопку, поменять значение переменной в коде ардуины.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

stupiddev пишет:

 можно ли ?

Трудно сказать, нужно у Клапауция спрашивать... Если он не запретил ещё, то можно. Я -то сам не против, если чо.

stupiddev
Offline
Зарегистрирован: 26.11.2019

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

ну это просто .надо нанять людей.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Если почитать про Serial ардуинки, то может наступить просветление. Но тут 50/50.

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

stupiddev пишет:

Всем привет. Есть небольшой вопрос. В общем у меня есть скетч ардуино, и есть приложение на питоне(gui) для работы с com-портом ардуины. Так вот вопрос в том, можно ли через этот же интерфейс на питоне, по нажатию на кнопку, поменять значение переменной в коде ардуины.

можно

stupiddev пишет:

Имелось ввиду, есть ли уже существующие способы для этого. И если есть, то как это сделать.

примеров, где ардуина зажигает лампочку по команде из Монитора компорта - пруд пруди. Для ардуины разницы между  Монитором и программой на питоне никакой нет

stupiddev
Offline
Зарегистрирован: 26.11.2019
int num = 0;
char sym;
String menu = "";
String mode;

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  if (Serial.available() > 0) {
  mode = Serial.readString();
  if (mode == "l"){
  mode = "";
  menu = Serial.readString();
  int len = menu.length();
  while (num < len) {
       sym = menu.charAt(num);
       Serial.print(sym);
       switch(sym){
        case 'A':
          case 'a': 
            delay(3000);
            dot();
            delay(500);
            dash();
            break;
}
       num++;
  } 
  }
 }
  menu = "";
  mode = "";
  num = 0;
  Serial.flush();
}

Я посмотрел уже, но у меня немного не получается, если не составит труда, попрошу помочь.
Вот тут у меня должна считываться переменная mode с COM-порта (на com порт значение идет из приложения питона), а потом в зависимости от того что пришло в эту переменную, продолжалась бы программа, но у меня почему то после считывания первой переменной (mode), не работает кусок кода, if (mode == 'l'), даже если в эту переменную пришла l.
Подозреваю, что после того как первая переменная была сочтена с ком порта, вторая уже не считывается

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

А если в 13 строкt сделать Serial.read()? Serial.readString() требует конца строки. А лучше, уважаемый, передавайте не символы, а цифры - оно как-то правильнее и работать с ними проще.

stupiddev
Offline
Зарегистрирован: 26.11.2019

С Serial.read() тоже не работает. С числами могу работать только с первой переменной(mode), во второй нужны именно символы.

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

stupiddev пишет:

С Serial.read() тоже не работает. С числами могу работать только с первой переменной(mode), во второй нужны именно символы.

открою страшную тайну - в компьютере даже символы - это тоже числа

stupiddev
Offline
Зарегистрирован: 26.11.2019

Я вкурсе, в коде приведенном выше(switch) я вставил всего один case, на самом деле их 33, и переделывать такие же 33 кейса, не с символами, а с числами для меня пока что извращение

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

похоже не в курсе, ваш свитч переписывать не нужно, просто вместо readstring используйте read

ваша первая проблема в том, что при чтении в строчку mode вы читаете не символ '1'. а строчку "1\r\n" - поэтому условие

if (mode == "l")

не сраьбатывает

 

stupiddev
Offline
Зарегистрирован: 26.11.2019

То есть если я просто перепишу readstring на read, то должно работать?

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

stupiddev пишет:

То есть если я просто перепишу readstring на read, то должно работать?

скорее всего нет, я же сказал. что это ТОЛЬКО ПЕРВАЯ проблема. Символы конца строки из обмена по Сериал никуда не денутся, их надо обрабатывать в коде - а вы этого не делаете, поэтому правильно работать не будет.

stupiddev
Offline
Зарегистрирован: 26.11.2019

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

FoxJone
Offline
Зарегистрирован: 19.04.2019

Читаю этот топик и чувствую, как ко мне возвращается самоуважение, существенно подорванное вчера неким СТМщиком в топике про RS-485.

Большое человеческое спасибо, ТС!)

Во-первых, прекратите считывать с компорта символы. Работайте с цифрой, только с цифрой и всегда с цифрой. У каждой кнопки на клавиатуре есть код. В питоне при нажатии на кнопку просто шлите один байт (который как раз равен этому коду) в компорт. Не печатайте в компорт текст, а просто пошлите байт. Питона не знаю, а в сях это оператор write. Соответственно ардуина как увидит этот байт (через Serial.available), пусть читает его оператором read. Все. А дальше делайте с ним, что хотите. Только не забывайте, почаще проверять состояние компорта, что бы не пропустить следующую клавишу.

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

stupiddev
Offline
Зарегистрирован: 26.11.2019

Я уже прислушался к совету выше, о работе с цифрами, попробовал. Да совет хороший, немного помогло, но сейчас проблема в том, что ком порт слушает только первую переменную, то есть переменную mode, в которую приходит буква l, далее срабатывает условие, но вторую переменную он считывать не хочет, что бы я не ввел в ком порт. И вторая моя ошибка, которую я не могу решить(имею представление как, но не выходит пока что), это то, что мне нужно делить вторую переменную(menu), на символы, начинается это с 17 строки, где нужно узнать длину строки. Как в данном случае работать с цифрами, ведь с цифрами метод length Не работает, просто конвертировать число в строку?Обычная конвертация числа в строку не даёт никаких результатов

stupiddev
Offline
Зарегистрирован: 26.11.2019

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

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

stupiddev пишет:

Ардуина считывает первую переменную и просто пропускает её дальше. В компорте выходит непонятный символ(видимо это буква l такая)

если в питоне вы "печатаете" символ в порт командой принт или типо того - "непонятный символ" это перевод строки 0x0A  - я писал об этом выше

stupiddev
Offline
Зарегистрирован: 26.11.2019

Из питона по нажатию кнопки, в ком порт шлется символ l, командой write

self.realport.write(b'l')

 

FoxJone
Offline
Зарегистрирован: 19.04.2019

Я так понимаю, проблема у вас на стороне компьютера. Вы совершенно не понимаете, что шлете в компорт и как это надо делать.

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

С питоном я вам, к сожалению, помочь не могу.

stupiddev
Offline
Зарегистрирован: 26.11.2019

Это проблема не на стороне питона. Я пробовал запускать приложение питона и слать символ, код скетча считывал первую переменную, эту букву l, пропускал второе считывание другой переменной. Дальше идет вычисление длины строки, чтобы это сделать я переменную с l конвертирую в строку, и эта строка идет в цикл. Вместо буквы l выходит непонятный мне символ, и т.к. в default указано просто зажжение диода, он зажигается. То же самое проделывал не из питона, а из монитора ком порта ардуино, происходило то же самое. Ошибка кроется в скетче, а не в коде программы питона. В питоне все предельно просто, по нажатию кнопки он шлет на ком порт(командой write) символ, и тоже самое проделывает если я в окошко напишу текст(с этого окошка как раз и должна считываться вторая переменная в ардуино).
Надеюсь я нигде не ошибся и объяснил понятно))

stupiddev
Offline
Зарегистрирован: 26.11.2019

Вместо буквы l выходит непонятный символ, скорее всего из-за того, что я символ l пришедший в виде числа из ком порта, конвертирую в строку

FoxJone
Offline
Зарегистрирован: 19.04.2019

Так. Давайте разберемся, что вы вообще хотите. Сначала я вас понял так, что вы хотите получать команды с клавиатуры (как с пульта). Потому что звучало так:

stupiddev пишет:

по нажатию на кнопку, поменять значение переменной в коде ардуины.

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

Как это вообще должно работать, можете описать? С примерами?

stupiddev
Offline
Зарегистрирован: 26.11.2019

Я опишу общую задумку. На ардуине есть баззер и светодиод
Хочу написать небольшое проект типа переводчика текста в Азбуку Морзе, для чего собственно там свитч и стоит

Сначала делал только со светодиодом. Все работало прекрасно

Потом на интерфейс приложения питона добавил 2 RadioButton'a, с выбором режима работы(Диод, либо баззер). Так же в интерфейсе есть текстовое поле в которое соответственно водится слово, которое нужно проморгать или пропикать. При нажатии на RadioButton, он должен слать на ком порт букву l, чтобы она заносилась в переменную и от этой переменной зависело бы как работала бы программа(моргала или пикала), после приема буквы l, if (mode == 'l') должна с ком порта заполнятся вторая переменная menu, это уже текст, который был введет в поле в приложении и отправлен на ком порт, после приема текста, вычисляется длина строки(menu.length) и в цикле перебирается каждый символ строки, сравнивается с значениями кейсов и светодиод моргает эти символы по отдельности. Для баззера ещё кейсы и функции для пропикивания не писал, но оно пока и не зачем, т.к. у меня не работает считывание переменных))
Надеюсь все предельно понятно объяснил, и очень надеюсь на вашу помощь, т.к. в ардуино я пока что слаб))

stupiddev
Offline
Зарегистрирован: 26.11.2019

Как я понял, после считывания первой переменной, срабатывает условие и видимо эта переменная идет дальше в цикл, превращаясь в строку и вместо той самой буквы l в цикл попадает какой-то непонятный символ, поэтому и срабатывает условие default

FoxJone
Offline
Зарегистрирован: 19.04.2019

Ваша ошибка, что вы почему то считаете, что вы в компорт шлете две разные посылки. С точки зрения вашего же скетча вы шлете одну посылку, которая выглядит как строка "l+текст+конец строки" (про конец строки не уверен - питона не знаю).

И в вашем скетче вы вот тут:  mode = Serial.readString(); считываете ВСЮ эту строку. И потом пытаетесь еще что то считать, а там уже ничего нет.

Ну это что сразу в глаза бросилось.

stupiddev
Offline
Зарегистрирован: 26.11.2019
const int buzzerPin = 9;
const int ledPin = 13;
int num = 0;
char sym;
String buf;
String menu;
int mode;

void setup() {
  pinMode(buzzerPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void dot() {
  digitalWrite(ledPin, HIGH);
  delay(500);
  digitalWrite(ledPin, LOW);
}

void dash() {
  digitalWrite(ledPin, HIGH);
  delay(1100);
  digitalWrite(ledPin, LOW);
}

void loop()
{
  {
    while (Serial.available() > 0) {
      mode = "";
      mode = Serial.read();
      //Serial.write(mode);
      if (mode == 'l')
      {
        mode = "";
        mode = Serial.read();
        buf = String(mode);
        int len = buf.length();
        //Serial.print(len);
        while (num < len)
        {
          sym = buf.charAt(num);
          switch (sym)
          {
            case 'A':
            case 'a':
              delay(3000);
              dot();
              delay(500);
              dash();
              break;
          }
          num++;
        }
      }
    }
  }
  mode = "";
  menu = "";
  num = 0;
  Serial.flush();
}

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

stupiddev
Offline
Зарегистрирован: 26.11.2019

case оставил только один, чтобы не вставлять сюда 300+ строк

FoxJone
Offline
Зарегистрирован: 19.04.2019

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

27 void loop()
28 {
29   {
30     while (Serial.available() > 0) {
 
32       buf = Serial.readString();
 
34       if (buf[0] == 'l')
35       {
39         int len = buf.length();
40         //Serial.print(len);
41         while (num < len)
42         {
43           sym = buf.charAt(num);
44           switch (sym)
45           {
46             case 'A':
47             case 'a':
48               delay(3000);
49               dot();
50               delay(500);
51               dash();
52               break;
53           }
54           num++;
55         }
56       }
57     }
58   }
59   mode = "";
60   menu = "";
61   num = 1; //потому что num = 0 у нас команда l или вторая
62   Serial.flush();

В остальном тоже бардак, но вроде работать будет (не проверял). И я бы уж точно не делал 33 case, а прошил бы в еепром азбуку морзе массивом и вызывал бы по букве.

FoxJone
Offline
Зарегистрирован: 19.04.2019

И перетащите инициализацию num наверх, а то при первом проходе она вообще не понятно какое значение имеет.

stupiddev
Offline
Зарегистрирован: 26.11.2019

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

FoxJone
Offline
Зарегистрирован: 19.04.2019

buf = Serial.readString(); считывает всю строку. L+текст

buf[0] - это команда, а buf[1-len] - это текст

Я вам только считывание поправил, а что у вас там в case твориться, даже не лезю

stupiddev
Offline
Зарегистрирован: 26.11.2019

Спасибо, со светодиодом сейчас все работает, подправил еще немного приложение питона. Очень благодарен Вам.

stupiddev
Offline
Зарегистрирован: 26.11.2019

У меня есть ещё один вопрос, но тут просто посоветоваться, надеюсь подскажешь.

У меня программа сейчас работает только с латиницей, т.к. латиница приходит в ком порт обычными символами, а кириллица кодируется в символы типа "\xd0\xb0\xd0\xb0\xd0\xb0". Из этого у меня вопрос вышел. Можно ли эти символы на стороне ардуины декодировать обратно в текст. И если нет, то можно ли прикрутить в скетч ардуины базу данных?

FoxJone
Offline
Зарегистрирован: 19.04.2019

Вот тут вам точно в питон надо смотреть.

Потому что если вы запустите стандартный ардуиновский монитор порта и в нем наберете "lпривет", то ардуина должна понять кириллицу. 

Попробуйте.

stupiddev
Offline
Зарегистрирован: 26.11.2019

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

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

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

stupiddev пишет:

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

можно

Цитата:
Если нет, то я впринципе уже придумал выход из этой ситуации, но для этого нужно будет прикрутить базу данных

а вот это вряд ли

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

stupiddev пишет:

Хочу написать небольшое проект типа переводчика текста в Азбуку Морзе, для чего собственно там свитч и стоит

Дед мне помогал в написании Маяка, посмотри тему Маяк на ардуино, там есть всё, в том числе разбор текста и вывод морзянки, получает текст из компорта естественно

stupiddev
Offline
Зарегистрирован: 26.11.2019

b707 пишет:

можно

а вот это вряд ли

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

FoxJone
Offline
Зарегистрирован: 19.04.2019

Я вам чем мог, помог. Но на сегодня запас моей доброты иссяк)

Перекодировать можно, но как именно - надо думать, а мне лень.

А вообще, мне кажется, что вы какую то фигню на питон наговариваете. Все известные мне языки умеют строку в компорт и в кириллице в том числе.

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

stupiddev пишет:

Если не сложно, не могли бы подсказать как.

в той строчке "\xd0\xb0\xd0\xb0\xd0\xb0". что вам кажется абракадаброй - на самом деле каждый символ \xd0 или каждые два символа (в зависимости от кодировки) - соответвуют букве. Так что перекодировка делается примерно так же, как вы превращаете латиницу в азбуку морзе - каждой букве сопоставлена своя последовательность, выбираемая через switch - case или, что удобнее - через массив

Цитата:

И почему вряд-ли?В ардуино нету баз данных?

В классической ардуине всего 2Кбайта оперативки. Ну какие тут базы данных, о чем вы вообще?

Кроме того, использовать БД лишь для перекодирования строк - это как пачку бумаги возить на 20-тонном Камазе

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

FoxJone пишет:

А вообще, мне кажется, что вы какую то фигню на питон наговариваете. Все известные мне языки умеют строку в компорт и в кириллице в том числе.

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

Но он явно пока не готов к этому знанию