Arduino Nano + HC05 передача аналогового сигнала и импульсного энкодера по ВТ

mgax
Offline
Зарегистрирован: 19.02.2020

День добрый!

Есть два устройства Master (Arduino Nano + HC05)  и Slave (Arduino Nano + HC05+MCP4725). Master получает : 1. аналоговый сигнал 0-5В (можно передавать раз в 200 мс), 2. сигналы с импульсного энкодера (А и В с максимальной частотой до 5 кГц) и один дискретный сигнал (сигнал аварии), все эти сигналы нужно передать на Slave устройство и выдать с МК. HC-05 настроены и работают без проблем.

Проблема с выходом на ЦАП (она меня беспокоит меньше всего) и вторая с сигналами энкодера на Slave, подаю с генератора только на вход D10 Master устройства (~50 Гц, ~600 Гц и ~4 кГц), на Slave, не пойми что, изменения видны на фронтах, бред какой-то.

Master code

int analog = 0;
int count = 0;
byte f = 0;
 
void setup()
{
  DDRB = B11100011; //d10 - сигнал А энкодера, d11 - сигнал В энкодера, d12 - сигнал аварии
  Serial.begin(115200);   
}
 
void loop()
{

      if (PINB == B00011100 & f != 1){Serial.print('a'); f = 1;}// 0x61 сканируем три дискретных входа (А и В энкодера и сигнал аварии)
      if (PINB == B00011000 & f != 2){Serial.print('b'); f = 2;}// 0x62 сканируем три дискретных входа (А и В энкодера и сигнал аварии)
      if (PINB == B00010000 & f != 3){Serial.print('c'); f = 3;}// 0x63 сканируем три дискретных входа (А и В энкодера и сигнал аварии)
      if (PINB == B00000000 & f != 4){Serial.print('d'); f = 4;}// 0x64 сканируем три дискретных входа (А и В энкодера и сигнал аварии)
      if (PINB == B00001100 & f != 5){Serial.print('e'); f = 5;}// 0x65 сканируем три дискретных входа (А и В энкодера и сигнал аварии)
      if (PINB == B00010100 & f != 6){Serial.print('f'); f = 6;}// 0x66 сканируем три дискретных входа (А и В энкодера и сигнал аварии)
      if (PINB == B00000100 & f != 7){Serial.print('g'); f = 7;}// 0x67 сканируем три дискретных входа (А и В энкодера и сигнал аварии)
      if (PINB == B00001000 & f != 8){Serial.print('h'); f = 8;}// 0x68 сканируем три дискретных входа (А и В энкодера и сигнал аварии)


     count++;
      
        if (count >= 32766){   // раз в какой-то промежуток времени считываем аналоговый сигнал и передаем по блютуз
            analog = analogRead(A0);              
            analog = analog * 0.05; //1023*0.05=51 (0x51) специально умножаю на 0.05, чтобы максимальный сигнал не превысил 0x51 и не смешался с символами, они начинаются с 0x61
            Serial.print(analog);
            count = 0;
        }
}

Slave code

#include <Adafruit_MCP4725.h>

Adafruit_MCP4725 dac;
uint32_t MCP4725_value = 0;

int result = 0;
 
void setup()
{
  dac.begin(0x60);
  DDRB = B11111111;
  Serial.begin(115200);
}
void loop()
{

 if (Serial.available()) {
  
    result = Serial.read();

    if (result == 'a'){PORTB = B00011100;}
    if (result == 'b'){PORTB = B00011000;}
    if (result == 'c'){PORTB = B00010000;}
    if (result == 'd'){PORTB = B00000000;}
    if (result == 'e'){PORTB = B00001100;}
    if (result == 'f'){PORTB = B00010100;}
    if (result == 'g'){PORTB = B00000100;}
    if (result == 'h'){PORTB = B00001000;}
    
    if (result != 'a' & result != 'b' & result != 'c' & result != 'd' & result != 'e' & result != 'f' & result != 'g' & result != 'h') { // писал и так if (result <= 51){
      MCP4725_value = result * 79;// 0x51 * 79 = 4029 (4095 макс), на выходе ЦАП всегда масимум, почему хз, отдельно - ЦАП работает четко
      dac.setVoltage(MCP4725_value, false);
      }
    }
}

 

rkit
Offline
Зарегистрирован: 23.11.2016

mgax пишет:

            analog = analog * 0.05; //1023*0.05=51 (0x51) специально умножаю на 0.05, чтобы максимальный сигнал не превысил 0x51 и не смешался с символами, они начинаются с 0x61
 

Наверно не надо целочисленное число умножать на дробь. Она просто округлится.

mgax
Offline
Зарегистрирован: 19.02.2020

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

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

А ты напечатай analog ДО этой строчки

analog = analog * 0.05

и после. И нам расскажи.

mgax
Offline
Зарегистрирован: 19.02.2020

Хорошо, как мне тогда передать информацию о дискретных входах и значение с аналогового входа в моей схеме? На плате Slave убираю все лишнее и пишу

result = 1023;

в основном цикле

MCP4725_value = result * 0.05;
dac.setVoltage(MCP4725_value, false);
 
На выходе ЦАП все четко (5/4095 *1023*0.05=0.062 В)
Все правильно. В чем вопрос?? На мастер плате я считываю аналоговый вход, допустим 5 В =1023 и заношу это в analog, далее analog = 1023 * 0.05 = 51.15, на самом деле в analog запишется 51. Что не правильно???
 
Основной вопрос по импульсам, почему такая картина????
DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

mgax пишет:

Что не правильно???

С виду, всё праильна. 

mgax
Offline
Зарегистрирован: 19.02.2020

А на практике, не работает.

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

mgax пишет:

Основной вопрос по импульсам, почему такая картина????

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

mgax
Offline
Зарегистрирован: 19.02.2020

Так и планировал, за счет чего должна искажаться форма сигнала (асинхронная передача?), символ отправил, символ получил. Как тогда можно сделать с учетом arduino nano и hc-05??? Очень важна беспроводная передача необходимых мне сигналов.

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

mgax пишет:

Так и планировал, за счет чего должна искажаться форма сигнала, символ отправил, символ получил. Как тогда можно сделать с учетом arduino nano и hc-05???

вы слово "асинхронный" понимаете? - символы отправляются не мгновенно, а когда контроллер найдет время для отправки. Вы , например, послали в Сериал 3 символа с интервалами в 1мс - а они там зависли и отправились все вместе спустя 3 мс

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

mgax
Offline
Зарегистрирован: 19.02.2020

 "символы отправляются не мгновенно, а когда контроллер найдет время для отправки. Вы , например, послали в Сериал 3 символа с интервалами в 1мс - а они там зависли и отправились все вместе спустя 3 мс"

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

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

mgax пишет:

Я считал, что если контроллер не чаще, чем раз в 200 мкс будет передавать байт (символ), все получится

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

Кроме того, "раз в 200мкс" явно мало для отслеживания фронтов на 4КГц

mgax
Offline
Зарегистрирован: 19.02.2020

Пусть не 200 мкс, 50 все равно не мало. Но я понял, по блютуз не прокатит, буду что-то другое думать. Благодарю b707 за разъяснения!!!

Думаю, что тема закрыта!

mgax
Offline
Зарегистрирован: 19.02.2020

Интересно, nRF24L01 подойдет?

mgax
Offline
Зарегистрирован: 19.02.2020

 Похоже на то, что nRF24L01 не подойдет, на максимальной скорости время между пакетами 620 мкс.

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

я вам в #9 написал, что подойдет. Вам нужна низкоуровневая передача. Любой протокол, "надстроенный" над нижним уровнем, дает слишком большой оверхед.

mgax
Offline
Зарегистрирован: 19.02.2020

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

Могу вкратце описать что и куда, если интересно!

mgax
Offline
Зарегистрирован: 19.02.2020

Вот приобрел RF 433. Пока не заработал. Где ошибка???

Master

#include <iarduino_RF433_Transmitter.h>           // Подключаем библиотеку для работы с передатчиком FS1000A
iarduino_RF433_Transmitter radio(4);              // Указываем номер вывода к которому подключён передатчик
int                        data[2];               // Создаём массив для передачи данных

int analog = 0;
int digital = 0;
unsigned int count = 0;
byte f = 0;

void setup(){
    DDRB = B11100011;
    
    radio.begin();                                 // Инициируем работу передатчика FS1000A
    radio.setDataRate     (i433_5KBPS);            // Указываем скорость передачи данных кбит/с
    radio.openWritingPipe (5);                     // Открываем 5 трубу для передачи данных
}                                                  
void loop(){

      if (PINB == B00011100 & f != 1) {digital = 1; f = 1;}
      if (PINB == B00011000 & f != 2) {digital = 2; f = 2;}
      if (PINB == B00010000 & f != 3) {digital = 3; f = 3;}
      if (PINB == B00000000 & f != 4) {digital = 4; f = 4;}
      if (PINB == B00001100 & f != 5) {digital = 5; f = 5;}
      if (PINB == B00010100 & f != 6) {digital = 6; f = 6;}
      if (PINB == B00000100 & f != 7) {digital = 7; f = 7;}
      if (PINB == B00001000 & f != 8) {digital = 8; f = 8;}
      
     count++;
      
        if (count >= 32767){
            analog = analogRead(A0);              
            count = 0;
        }
  
    data[0] = digital;                             
    data[1] = analog;                            
    radio.write(&data, sizeof(data));              // отправляем данные из массива data (
    delayMicroseconds(10);                         // пауза между пакетами
}

 

Slave

#include <iarduino_RF433_Receiver.h>                      // Подключаем библиотеку для работы с приёмником
#include <Adafruit_MCP4725.h>

Adafruit_MCP4725 dac;
uint32_t MCP4725_value = 0;

int result = 0;

iarduino_RF433_Receiver radio(2);                        // Указываем номер вывода к которому подключён приёмник 
int                     data[2];                         // Создаём массив для приёма данных

void setup(){

    dac.begin(0x60);
    DDRB = B11111111;

    radio.begin();                                        // Инициируем работу приёмника MX-RM-5V
    radio.setDataRate     (i433_5KBPS);                   // Указываем скорость приёма данных кбит/сек
    radio.openReadingPipe (5);                            // Открываем 5 трубу для приема данных 
    radio.startListening  ();                             // Включаем приемник, начинаем прослушивать открытую трубу

}
void loop(){
  
    if(radio.available()){                                // Если в буфере имеются принятые данные
      
        radio.read(&data, sizeof(data));                  // Читаем данные в массив data и указываем сколько байт читать
        
        result = data[0];
        
        if (result == 1){PORTB = B00011100;}
        if (result == 2){PORTB = B00011000;}
        if (result == 3){PORTB = B00010000;}
        if (result == 4){PORTB = B00000000;}
        if (result == 5){PORTB = B00001100;}
        if (result == 6){PORTB = B00010100;}
        if (result == 7){PORTB = B00000100;}
        if (result == 8){PORTB = B00001000;}

          MCP4725_value = data[1] * 4;
          dac.setVoltage(MCP4725_value, false);

    }                                                     
}

 

 

mgax
Offline
Зарегистрирован: 19.02.2020

Пробовал и с другой библиотекой! Не работает, данные передаются, но программа не отрабатывает, вообще!

Master

#include <RCSwitch.h>
byte f = 0;
RCSwitch mySwitch = RCSwitch();

void setup() {
    DDRB = B11100011;
    mySwitch.enableTransmit(4);// вывод D4
}

void loop() {

      if (PINB == B00011100 & f != 1) {mySwitch.send(B111, 3); f = 1;} // передаем три бита mySwitch.send(B111, 3)

      if (PINB == B00011000 & f != 2) {mySwitch.send(B110, 3); f = 2;}
      if (PINB == B00010000 & f != 3) {mySwitch.send(B100, 3); f = 3;}
      if (PINB == B00000000 & f != 4) {mySwitch.send(B000, 3); f = 4;}
      if (PINB == B00001100 & f != 5) {mySwitch.send(B011, 3); f = 5;}
      if (PINB == B00010100 & f != 6) {mySwitch.send(B101, 3); f = 6;}
      if (PINB == B00000100 & f != 7) {mySwitch.send(B001, 3); f = 7;}
      if (PINB == B00001000 & f != 8) {mySwitch.send(B010, 3); f = 8;}
      
      delayMicroseconds(10);
}

Slave

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();

void setup() {
    DDRB = B11111111;
    mySwitch.enableReceive(0);// INT0 вывод D2
}

void loop() {
    if( mySwitch.available() ){
      
        int result = mySwitch.getReceivedValue();
        
        if (result == B111){PORTB = B00011100;}
        if (result == B110){PORTB = B00011000;}
        if (result == B100){PORTB = B00010000;}
        if (result == B000){PORTB = B00000000;}
        if (result == B011){PORTB = B00001100;}
        if (result == B101){PORTB = B00010100;}
        if (result == B001){PORTB = B00000100;}
        if (result == B010){PORTB = B00001000;}
        
        mySwitch.resetAvailable();
    }
}