Прием данных из COM порта - прошу помощи.

kolyan7007
Offline
Зарегистрирован: 29.05.2017

Приветствую дорогие форумчане!

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

80 светодиодов, 8 сдвиговых регистров 74HC595, защелка каждого регистра подключена на отдельный выход ардуино, Arduino UNO .

После того как мы на простейшем примере научились управлять светодиодом через COM порт и научились управлять сдвиговыми регистрами(так же на примерах). Было решено это все соединить воедино.Мысли такие:

1) С компа отправляем команду: "R1,00000001"- где "R1"- номер регистра(номер пина ардуино к которому подключена защелка первого регистра), "00000001"- включаемый светодиод(двоичное число, его можно заменить десятичным)

2) Ардуино слушает COM порт, полученную команду записывает в буфер, из буфера сначала отделяет номер регистра, а потом записывает на этот  регистр число которое соответствует включенным светодиодам.

 Другие регистры не изменяют своего состояния(мы их защелки не дергаем) вот ссылки на примеры из сети которые я питаюсь адаптировать под себя, но ничего не выходит

http://forum.amperka.ru/threads/%D0%9E%D1%80%D0%B3%D0%B0%D0%BD%D0%B8%D0%...   

http://podrugomu.com/node/987

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

/*Опыт № 10 Папа и Ярик программируют дуню*/
#include <SPI.h>//подкл. библиотеку 
enum { REG0 = 8, REG1 = 7 };//назначаем каждому регистру выходы выбора

/* функция записи в регистр */
void writeShiftRegister(int ss_pin, uint8_t value)
{
  digitalWrite(ss_pin, LOW);
  SPI.transfer(value);
  digitalWrite(ss_pin, HIGH);
}
int val; // освобождаем память в контроллере для переменой
int numberREG[] = {REG0, REG1};//массив с номерам регистров для выбора

void setup()
{
  Serial.begin(9600); // подключаем последовательный порт
  SPI.begin();//инициализ. последов. шины
  /* объявляем пины регистров как выходы */
  pinMode(REG0, OUTPUT);
  pinMode(REG1, OUTPUT);
/* обнуляем регистры*/ 
  writeShiftRegister(REG0, 0);
  writeShiftRegister(REG1, 0);
}


void loop()
{
 if (Serial.available()) // проверяем, поступают ли какие-то команды
  {

    val = Serial.read(); // переменная val равна полученной команде

    if (val == '0') {writeShiftRegister(REG0, 3);} // при 0 записываем на регистр число
    if (val == '1') {writeShiftRegister(REG1, 55);} // при 1 записываем на регистр число
    if (val == 'f') {writeShiftRegister(REG0, 0), writeShiftRegister(REG1, 0);} // при f обнуляем регистры
   
  } 

}

остается написать функцию которая будет из сообщения COM порта брать номер регистра и записывать в него десятичное число.

Помогите пожалуйста дописать код, немного осталось)))

Pavel982
Offline
Зарегистрирован: 28.05.2017

kolyan7007 пишет:
остается написать функцию которая будет из сообщения COM порта брать номер регистра и записывать в него десятичное число.

ищите на форуме scanf() от ЕвгенияП

kolyan7007
Offline
Зарегистрирован: 29.05.2017

Pavel982 пишет:

kolyan7007 пишет:
остается написать функцию которая будет из сообщения COM порта брать номер регистра и записывать в него десятичное число.

ищите на форуме scanf() от ЕвгенияП

Спасибо за ответ, читал тему про эту функцию, но не дошло до меня , еще пойду попробую)))

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

 Вы хотите организовать на SPI ? Под шилд http://arduinolearning.com/code/multi-function-shield-examples.php

/*Seg_displ_A.ino
   каскад из 2х  74РС595N (POS - '0' SEG)
   Latch->4;(Latch_pin) ->10
  CLK->7(CLK_pin)       ->13
  DI=8(DI_pin)          ->11
*/
//---------------------Cl_wire-----------------------
#include <SPI.h>
class Cl_wire {
    byte Latch_pin;
    byte max_device ;
  public:
    byte * buffer;
    Cl_wire(byte a, byte b): Latch_pin (a), max_device(b) {
      buffer = new byte[max_device];
    }
    //  setup
    setup() {
      SPI.begin();
      pinMode(Latch_pin, OUTPUT);
      digitalWrite(Latch_pin, LOW);
      for (int j = max_device - 1; j >= 0; --j )
        SPI.transfer(buffer[j] = 0x00);
      digitalWrite(Latch_pin, HIGH);
    }
    // запись
    void Write(byte adr, byte data) {
      buffer[adr] = data;
      digitalWrite(Latch_pin, LOW);
      for (int j = max_device - 1; j >= 0; --j )
        SPI.transfer(buffer[j]);
      digitalWrite(Latch_pin, HIGH);
    }
    // запись 2-х байт
    void Write2byte(byte adr1, byte data1, byte adr2, byte data2) {
      buffer[adr1] = data1;
      buffer[adr2] = data2;
      digitalWrite(Latch_pin, LOW);
      for (int j = max_device - 1; j >= 0; --j )
        SPI.transfer(buffer[j]);
      digitalWrite(Latch_pin, HIGH);
    }
};
//------------------------Cl_74HC595H-------------------
const byte Segment_font[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0X80, 0X90};//LOW
const byte Pos_font[] = {0xF8, 0xF4, 0xF2, 0xF1}; // HIGH
class Cl_74HC595H {
    Cl_wire *wire;//шина
    byte adr_p; // адрес ответ за позицию
    byte adr_s; // адрес ответ за цифру
    uint16_t data;// число на дисплее
    uint32_t past;
    byte i = 0;
  public:
    // конструктор
    Cl_74HC595H(Cl_wire *_wire, byte _adr_p, byte _adr_s): wire(_wire), adr_p(_adr_p), adr_s(_adr_s) {}
    void setup() {
      wire->Write2byte(adr_p, 0x00, adr_s, 0xFF);
    }
    void write(byte pos, byte data) {
      wire->Write2byte(adr_s, Segment_font[data], adr_p, Pos_font[pos]);
    }
    void write(uint16_t _data) {
      data = _data;
    }
    void loop() {
      write(0, data % 10);
      write(1, data / 10 % 10);
      write(2, data / 100 % 10);
      write(3, data / 1000 % 10);
    }
};
//------------------------------------------------------------

Cl_wire wire(4, 20);
//Cl_wire wire(4, 7, 8, 20);
Cl_74HC595H Pos(&wire, 0, 1);

void setup () {
  wire.setup();
  Pos.setup();
  Pos.write(1234);
}
void loop() {
  Pos.loop();
}

 

Pavel982
Offline
Зарегистрирован: 28.05.2017

kolyan7007 пишет:
Pavel982 пишет:
ищите на форуме scanf() от ЕвгенияП
Спасибо за ответ, читал тему про эту функцию, но не дошло до меня , еще пойду попробую)))
Ищите тему, в которой ЕвгенийП выложил тексты и примеры использования им написанных версий функций printf() и scanf()

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

Есть еще скетч Пакет здесь  https://yadi.sk/d/WaW7iUgj3GPUvp

/*Wire_74HC595.ino 
*/
const int Latch_pin = 3;
const int CLK_pin  = 4;
const int Data_pin = 2;
const int max_device = 4;
bool stat = 0;
#include "Out_74HC595.h"
Out_74HC595 Out(Latch_pin, CLK_pin, Data_pin, max_device);
#include "Cl_led.h"
Cl_led led[] = {
  Cl_led(&Out, 0, 1, 0),  // шина-Out,1 горит,1-я 74HC595,D0
  Cl_led(&Out, 0, 1, 1),  // шина-Out,1 горит,1-я 74HC595,D1
  Cl_led(&Out, 0, 1, 2),  // шина-Out,1 горит,1-я 74HC595,D2
  Cl_led(&Out, 0, 1, 3)   // шина-Out,1 горит,1-я 74HC595,D3
};
void setup() {
  Out.setup();
  for (byte i = 0; i < 4; i++)  led[i].setup();
  led[0].blink(100);
  led[1].blink(150);
  led[2].blink(500);
  led[3].blink(1000);
}

void loop() {
  for (byte i = 0; i < 4; i++)  led[i].loop();
}

 

kolyan7007
Offline
Зарегистрирован: 29.05.2017

qwone пишет:

 Вы хотите организовать на SPI ? Под шилд http://arduinolearning.com/code/multi-function-shield-examples.php

/*Seg_displ_A.ino
   каскад из 2х  74РС595N (POS - '0' SEG)
   Latch->4;(Latch_pin) ->10
  CLK->7(CLK_pin)       ->13
  DI=8(DI_pin)          ->11
*/
//---------------------Cl_wire-----------------------
#include <SPI.h>
class Cl_wire {
    byte Latch_pin;
    byte max_device ;
  public:
    byte * buffer;
    Cl_wire(byte a, byte b): Latch_pin (a), max_device(b) {
      buffer = new byte[max_device];
    }
    //  setup
    setup() {
      SPI.begin();
      pinMode(Latch_pin, OUTPUT);
      digitalWrite(Latch_pin, LOW);
      for (int j = max_device - 1; j >= 0; --j )
        SPI.transfer(buffer[j] = 0x00);
      digitalWrite(Latch_pin, HIGH);
    }
    // запись
    void Write(byte adr, byte data) {
      buffer[adr] = data;
      digitalWrite(Latch_pin, LOW);
      for (int j = max_device - 1; j >= 0; --j )
        SPI.transfer(buffer[j]);
      digitalWrite(Latch_pin, HIGH);
    }
    // запись 2-х байт
    void Write2byte(byte adr1, byte data1, byte adr2, byte data2) {
      buffer[adr1] = data1;
      buffer[adr2] = data2;
      digitalWrite(Latch_pin, LOW);
      for (int j = max_device - 1; j >= 0; --j )
        SPI.transfer(buffer[j]);
      digitalWrite(Latch_pin, HIGH);
    }
};
//------------------------Cl_74HC595H-------------------
const byte Segment_font[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0X80, 0X90};//LOW
const byte Pos_font[] = {0xF8, 0xF4, 0xF2, 0xF1}; // HIGH
class Cl_74HC595H {
    Cl_wire *wire;//шина
    byte adr_p; // адрес ответ за позицию
    byte adr_s; // адрес ответ за цифру
    uint16_t data;// число на дисплее
    uint32_t past;
    byte i = 0;
  public:
    // конструктор
    Cl_74HC595H(Cl_wire *_wire, byte _adr_p, byte _adr_s): wire(_wire), adr_p(_adr_p), adr_s(_adr_s) {}
    void setup() {
      wire->Write2byte(adr_p, 0x00, adr_s, 0xFF);
    }
    void write(byte pos, byte data) {
      wire->Write2byte(adr_s, Segment_font[data], adr_p, Pos_font[pos]);
    }
    void write(uint16_t _data) {
      data = _data;
    }
    void loop() {
      write(0, data % 10);
      write(1, data / 10 % 10);
      write(2, data / 100 % 10);
      write(3, data / 1000 % 10);
    }
};
//------------------------------------------------------------

Cl_wire wire(4, 20);
//Cl_wire wire(4, 7, 8, 20);
Cl_74HC595H Pos(&wire, 0, 1);

void setup () {
  wire.setup();
  Pos.setup();
  Pos.write(1234);
}
void loop() {
  Pos.loop();
}

 

От каскадного подключения регистров я отказался, мне показалось что проще будет выбирать нужный регистр и на него записывать данные, чем перезаписывать данные на всех регистрах. А по SPI как то проще, не надо в коде указывать к каким пинам что подключено(хотя я могу заблуждаться)

Указанный вами шилд не использую

kolyan7007
Offline
Зарегистрирован: 29.05.2017

Pavel982 пишет:

kolyan7007 пишет:
Pavel982 пишет:
ищите на форуме scanf() от ЕвгенияП
Спасибо за ответ, читал тему про эту функцию, но не дошло до меня , еще пойду попробую)))
Ищите тему, в которой ЕвгенийП выложил тексты и примеры использования им написанных версий функций printf() и scanf()

Хорошо, сейчас займусь изучением. Спасибо!

Pavel982
Offline
Зарегистрирован: 28.05.2017

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

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

kolyan7007 пишет:

Приветствую дорогие форумчане!

80 светодиодов, 8 сдвиговых регистров 74HC595, защелка каждого регистра подключена на отдельный выход ардуино, Arduino UNO .

8 сдвиговых регистров 74HC595 - это не 80, а 64 выхода.

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

kolyan7007 пишет:
От каскадного подключения регистров я отказался, мне показалось что проще будет выбирать нужный регистр и на него записывать данные, чем перезаписывать данные на всех регистрах. А по SPI как то проще, не надо в коде указывать к каким пинам что подключено(хотя я могу заблуждаться)

Скорее вы заблуждаетесь. SPI  "освобождает",точнее навязывает вам  использовать CLK (13 прин) и MOSI()  А дальше выбор микросхемы такой же. 

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

10 регистров - 10 байт в памяти.  Да хоть 100.

Меняете биты в этих байтах и выводите всё в  регистры.
 

kolyan7007
Offline
Зарегистрирован: 29.05.2017

trembo  - Вы правы я ошибся, конечно 64 светодиода.

 

kolyan7007
Offline
Зарегистрирован: 29.05.2017

trembo пишет:

10 регистров - 10 байт в памяти.  Да хоть 100.

Меняете биты в этих байтах и выводите всё в  регистры.
 

Так получается если я их подключаю каскадом, то код проще получается? Не нужно разбирать строку принятую из COM порта на номер регистра и число коорое нужно записать в регистр?

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

kolyan7007 пишет:

trembo  - Вы правы я ошибся, конечно 64 светодиода.

И также вы ошибаетесь пытаясь параллельно выводить данные в последовательные регистры.
Помните чем закончилась эпоха PATA?
Правильно, появился SATA!

kolyan7007
Offline
Зарегистрирован: 29.05.2017

trembo пишет:

kolyan7007 пишет:

trembo  - Вы правы я ошибся, конечно 64 светодиода.

И также вы ошибаетесь пытаясь параллельно выводить данные в последовательные регистры.
Помните чем закончилась эпоха PATA?
Правильно, появился SATA!

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

1 продолжать и написать функцию для разбора строки

2 переделать под последовательный вывод данных на регистры

пока не решил как поступить...

Pavel982
Offline
Зарегистрирован: 28.05.2017

kolyan7007 пишет:
Так получается если я их подключаю каскадом, то код проще получается? Не нужно разбирать строку принятую из COM порта на номер регистра и число коорое нужно записать в регистр
разбирать все равно нужно, тк мк должен понять чем управлять. Но строку можно упростить

Например 0 выключить всё;

255 включить всё;

+45   включить LED №45; 

-45   вЫключить LED №45;

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Pavel982 пишет:

Например 0 выключить всё;

255 включить всё;

+45   включить LED №45; 

-45   вЫключить LED №45;

+45 Это если по одному включать.

А надо просто с компа передать столько байт сколько у вас регистров и всё

Где-то была готовая библиотека  по приёму и выводу байтов на светодиоды.
 

Pavel982
Offline
Зарегистрирован: 28.05.2017

trembo пишет:
+45 Это если по одному включать
Это как удобно автору темы,  можно по команде  +45 включить  45 LED

kolyan7007
Offline
Зарегистрирован: 29.05.2017

trembo пишет:

Pavel982 пишет:

Например 0 выключить всё;

255 включить всё;

+45   включить LED №45; 

-45   вЫключить LED №45;

+45 Это если по одному включать.

А надо просто с компа передать столько байт сколько у вас регистров и всё

Где-то была готовая библиотека  по приёму и выводу байтов на светодиоды.
 

8 регистров, 8-ми битное число, всего 64 байта(по байте на каждый выход) (это я больше для себя разжёвываю)

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

kolyan7007
Offline
Зарегистрирован: 29.05.2017

Pavel982 пишет:

trembo пишет:
+45 Это если по одному включать
Это как удобно автору темы,  можно по команде  +45 включить  45 LED

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

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Не 64 байта, а  8 байт, 64 бита которые напрямую просто выводятся в регистр.

kolyan7007
Offline
Зарегистрирован: 29.05.2017

trembo пишет:

Не 64 байта, а  8 байт, 64 бита которые напрямую просто выводятся в регистр.

Глаза на лоб чуть не вылезли, конечно 8 байт, 64 бита, сам не понял как перепутал! 1 байт= 8 бит

Прошу прощения