Arduino Nano + HC05 передача аналогового сигнала и импульсного энкодера по ВТ
- Войдите на сайт для отправки комментариев
Ср, 19/02/2020 - 12:11
День добрый!
Есть два устройства 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);
}
}
}
analog = analog * 0.05; //1023*0.05=51 (0x51) специально умножаю на 0.05, чтобы максимальный сигнал не превысил 0x51 и не смешался с символами, они начинаются с 0x61Наверно не надо целочисленное число умножать на дробь. Она просто округлится.
А мне и нужно в итоге получить целочисленное число, я так понимаю, компилятор должен отсечь все, что после запятой (округлить). Больше интересует проблема с сигналами энкодера
А ты напечатай analog ДО этой строчки
analog = analog * 0.05
и после. И нам расскажи.
Хорошо, как мне тогда передать информацию о дискретных входах и значение с аналогового входа в моей схеме? На плате Slave убираю все лишнее и пишу
result = 1023;
в основном цикле
Что не правильно???
С виду, всё праильна.
А на практике, не работает.
вы каждый фронт с энкодера хотите символом в Сериал передавать? - UART - асинхронный протокол, форма сигнала обязана искажаться. на что вы надеетесь?
Так и планировал, за счет чего должна искажаться форма сигнала (асинхронная передача?), символ отправил, символ получил. Как тогда можно сделать с учетом arduino nano и hc-05??? Очень важна беспроводная передача необходимых мне сигналов.
Так и планировал, за счет чего должна искажаться форма сигнала, символ отправил, символ получил. Как тогда можно сделать с учетом arduino nano и hc-05???
вы слово "асинхронный" понимаете? - символы отправляются не мгновенно, а когда контроллер найдет время для отправки. Вы , например, послали в Сериал 3 символа с интервалами в 1мс - а они там зависли и отправились все вместе спустя 3 мс
Никакой способ связи, использующий Сериал - не пожходит для этой задачи. Вохьмите самые обыкновенные приемники и передатчики 433 Мгц, сделайте прием по прерыванию - тогда есть надежда получить на приеме фронты, похожие на те, что отправляля. И желательно, чтобы ардуина больше ничего не делала
"символы отправляются не мгновенно, а когда контроллер найдет время для отправки. Вы , например, послали в Сериал 3 символа с интервалами в 1мс - а они там зависли и отправились все вместе спустя 3 мс"
Я считал, что если контроллер не чаще, чем раз в 200 мкс будет передавать байт (символ), все получится, тем более, что кроме сканирования порта и отправки байта мк ничем больше не занимается (если из программы убрать строки по АЦП, все тоже самое получается)
Я считал, что если контроллер не чаще, чем раз в 200 мкс будет передавать байт (символ), все получится
посмотрите на свои осцилограммы - разве они не подтверждают мои слова? - у вас символы отправляются не равномерно, а пачками.
Кроме того, "раз в 200мкс" явно мало для отслеживания фронтов на 4КГц
Пусть не 200 мкс, 50 все равно не мало. Но я понял, по блютуз не прокатит, буду что-то другое думать. Благодарю b707 за разъяснения!!!
Думаю, что тема закрыта!
Интересно, nRF24L01 подойдет?
Похоже на то, что nRF24L01 не подойдет, на максимальной скорости время между пакетами 620 мкс.
я вам в #9 написал, что подойдет. Вам нужна низкоуровневая передача. Любой протокол, "надстроенный" над нижним уровнем, дает слишком большой оверхед.
Да, да, я взял на заметку то, что Вы мне написали! Вообще, иногда сбоит вот такая штука (см. фото), сделана на контроллерах немцами, но сделать подобное на ардуино, сомнения!
Могу вкратце описать что и куда, если интересно!
Вот приобрел 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); } }Пробовал и с другой библиотекой! Не работает, данные передаются, но программа не отрабатывает, вообще!
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(); } }