Приемник 433MHz +ATTINY13 и библиотека RemoteSwitch

Foster777
Offline
Зарегистрирован: 20.07.2019

Здравствуйте!Нужна помощь знающих людей.Делаю автоматику для откатных ворот и вот столкнулся с необходимостью дистанционного управления приводом.В качестве пульта использую связку Attiny13 и передатчик FS1000A, скетч нашел в сети и подправил.На пульте только одна кнопка,при нажатии один раз отправляет код на приемник.При помощи библиотеки RemoteSwitch и примера Show_received_code.ino читаю код пульта:

Received 1394001 / 24bit Protocol: 1

.Отладку приемника делал на UNO ,но для одной функции думаю что ее применение излишне.В наличии есть некоторое количество ATTINY13. В сети по ссылке https://github-com.translate.goog/DROID8622/ATtiny13-433MHz-Receiver-Transmitter?_x_tr_sl=auto&_x_tr_tl=ru&_x_tr_hl=ru&_x_tr_pto=op нашел пример работы приемника и ATTINY13, но в описании скетча ATTINY13-433MHzRemoteSwitch.ino указан протокол работы   12 bit:

 Protocol used is known as protocol 12 from RCSwitch library.
 { 320, { 36, 1 }, { 1, 2 }, { 2, 1 }, true }
 ( 12 bits, pulselength is 320 microseconds , "1" is 640 low / 320 high , "0" is 640 high / 320 low, pilot period is 11520 (320*36).
 PROTOCOL is "inverted".

Но пульт передает 24 bit. Возможно ли  изменить протокол в скетче приемника на 24 bit?Сам додуматься не могу.Прошу помочь.

                                                                             

 

Foster777
Offline
Зарегистрирован: 20.07.2019

Код передатчика

Received 1394001 / 24bit Protocol: 1
data bits of pulse train duration: 38648
proposed protocol: { 399, { 1, 30 }, { 1, 3 }, { 3, 1 }, false }
====
first level down
12084 
756 1172 436 1156 432 1168 1200 396 420 1180 1196 404 412 1188 1192 408 
408 1188 1196 400 412 1188 416 1180 416 1180 1200 400 408 1192 1180 416 
404 1188 1184 412 400 1196 1180 416 400 1192 404 1188 408 1184 1192 404 
408
====

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016
#define rxPin PB1 //receiver
#define txPin PB3 // transmitter

 

Foster777
Offline
Зарегистрирован: 20.07.2019

ua6em пишет:

#define rxPin PB1 //receiver
#define txPin PB3 // transmitter

 

Ну это понятно.

void grab() {
rxstate = digitalRead(rxPin);
if (rxstate == HIGH)
lolen = micros() - prevtime;
else
hilen = micros() - prevtime;
prevtime = micros();

if (rxstate == LOW) {
if (CheckValue(320, hilen) && CheckValue(640, lolen)) {
// valid 1
cameCode = (cameCode << 1) | 1;
cameCounter++;
}
else if (CheckValue(640, hilen) && CheckValue(320, lolen)) {
// valid 0
cameCode = (cameCode << 1) | 0;
cameCounter++;
}
else cameCounter = 0;
} else if (lolen > 1000 && (cameCounter == 12 || cameCounter == 13) && ((cameCode & 0xfff) != 0xfff)) {
lastCode = cameCode & 0xfff;
cameCounter = 0;
cameCode = 0;
}
}

Что здесь исправить?

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

Foster777 пишет:

Что здесь исправить?

многое. Длину кода, маску, размерность переменной cameCode...

Foster777
Offline
Зарегистрирован: 20.07.2019
if (rxstate == LOW) {
10
	if (CheckValue(320, hilen) && CheckValue(640, lolen)) {
11
	// valid 1
12
	cameCode = (cameCode << 1) | 1;
13
	cameCounter++;
14
	}
15
	else if (CheckValue(640, hilen) && CheckValue(320, lolen)) {
16
	// valid 0
17
	cameCode = (cameCode << 1) | 0;
18
	cameCounter++;  

здесь как я понимаю прописываются тайминги.
{ 399, { 1, 30 }, { 1, 3 }, { 3, 1 }, false } это маска,да?

 

Foster777
Offline
Зарегистрирован: 20.07.2019

 переменная cameCode... должна быть  long.

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

Foster777 пишет:

 переменная cameCode... должна быть  long.


да. А вот все что выше - ерунда, не имеющая отношения к делу.

Foster777
Offline
Зарегистрирован: 20.07.2019

Имеется такой код передатчика

#include <avr/io.h>
#define txPin PB0
#define LED PB2
#define buttonPin PB1
volatile  uint8_t int0Flag = false;
void setup() {
  pinMode(txPin, OUTPUT);
  pinMode(buttonPin, INPUT);
  pinMode(LED, OUTPUT);
  attachInterrupt(0, flag, FALLING);
}
void loop() {
  if (int0Flag == true) {
    delay(20); //задержка для защиты от дребезга
    PORTB |= (1 << LED); // HIGH
    SendCame4(2211);
    delay(20);    // Задержка 50 мс (дребезг контактов)
    PORTB &= ~(1 << LED); // LOW
    while (digitalRead(buttonPin))
    {
      delay(200);
    }
    int0Flag = false;
  }
}
void SendCame4(long Code) {
  noInterrupts();
  for (int j = 0; j < 10; j++) { // посылку посылаем 10 раза подряд.
    // время стартового импульса
    digitalWrite(txPin, HIGH);
    delayMicroseconds(320);
    digitalWrite(txPin, LOW);
    for (int i = 12; i > 0; i--) {
      byte b = bitRead(Code, i - 1); // побитово перебираем и посылаем код
      if (b) {
        digitalWrite(txPin, LOW); // 1
        delayMicroseconds(640);
        digitalWrite(txPin, HIGH);
        delayMicroseconds(320);
      }
      else {
        digitalWrite(txPin, LOW); // 0
        delayMicroseconds(320);
        digitalWrite(txPin, HIGH);
        delayMicroseconds(640);
      }
    }
    digitalWrite(txPin, LOW);
    delayMicroseconds(11520);
  }
  interrupts();
}

void flag() {
  int0Flag = true;
}

Криво но работает,переделаю.Передает код 2211 , 12bit.

Код приемника

#define rxPin 2 //receiver
#define ledPin 4 // LED or relay
#define MAX_DELTA 200 // impulse lenght may vary of battery and so on, max deviation is 200
volatile static int lastCode = 0;
volatile unsigned long prevtime;
volatile unsigned int lolen, hilen, rxstate;
volatile static byte cameCounter = 0; // count of bits stored
volatile static int cameCode = 0; // code itself
boolean CheckValue(unsigned int base, unsigned int value) {
  return ((value == base) || ((value > base) && ((value - base) < MAX_DELTA)) || ((value < base) && ((base - value) < MAX_DELTA)));
}
void setup() {
  pinMode(rxPin, INPUT);
  pinMode(ledPin, OUTPUT);
  attachInterrupt(INT0, grab, CHANGE); //INT0 PB1 hardware interrupt
  //interrupts();
}

void loop() {

  if (lastCode == 2211) {
    digitalWrite(ledPin, HIGH);
    delay(20);
    digitalWrite(ledPin, LOW);
  }
  lastCode = 0;
}
void grab() {
  rxstate = digitalRead(rxPin);
  if (rxstate == HIGH)
    lolen = micros() - prevtime;
  else
    hilen = micros() - prevtime;
  prevtime = micros();

  if (rxstate == LOW) {
    if (CheckValue(320, hilen) && CheckValue(640, lolen)) {
      // valid 1
      cameCode = (cameCode << 1) | 1;
      cameCounter++;
    }
    else if (CheckValue(640, hilen) && CheckValue(320, lolen)) {
      // valid 0
      cameCode = (cameCode << 1) | 0;
      cameCounter++;
    }
    else cameCounter = 0;
  } else if (lolen > 1000 && (cameCounter == 12 || cameCounter == 13)) {
    lastCode = cameCode ;
    cameCounter = 0;
    cameCode = 0;
  }
}

Работает  на UNO и attyny13(с небольшими изменениями). Задача такая : после принятия кода один раз моргнуть светодиодом. Но моргает иногда несколько раз.

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

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Foster777 пишет:

 как конь в воде

Это как ???

Foster777
Offline
Зарегистрирован: 20.07.2019

Как дельфин,только на оборот. Самостоятельно изучаю, книги, ютуб,смотрю примеры кода,пробую.

Green
Offline
Зарегистрирован: 01.10.2015

Ну кони то плавают, хоть как то. В отличие от коров.)
У меня объект был с дельфинами. Для уничтожения пловцов. После него я дельфинов боялся офигенно как.(

Foster777
Offline
Зарегистрирован: 20.07.2019

Green пишет:

Ну кони то плавают, хоть как то. В отличие от коров.)
У меня объект был с дельфинами. Для уничтожения пловцов. После него я дельфинов боялся офигенно как.(

Коровы нормально плавают.Я деревенский и видел как одна буренка ставок пересекала.

Green
Offline
Зарегистрирован: 01.10.2015

Хе-хе. Ну, значит это мой пробел.)

Foster777
Offline
Зарегистрирован: 20.07.2019

Вот скетч для привода откатных ворот:

// Распиновка Аттини 2313
#include <util/delay.h>
#define LED_FLASH_GREEN 10            // светодиод ----- PORTPB1
#define Swihc_Open_PIN 0              // концевик "Открыто"
#define Swihc_Close_PIN 1             // концевик "Закрыто"
#define Fotoelement_PIN 5             // вход ИК датчика препятствия
#define Button_State_PIN 7            // кнопка переключения режимов "Открыть-Стоп-Закрыть"
#define Close_Rele_Pin 8              //выход на реле ЗАКРЫТЬ ---- PORTPD6
#define Open_Rele_Pin 12             //выход на реле ОТКРЫТЬ ---- PORTPB3
#define Power_TRANS_PIN 13           // выход на реле трансформатора питания привода мотора ---- PORTPB4
#define Rele_Unbloking_PIN 14        //выход на реле механизма блокировки движения ворот ---- PORTPB5
#define MOTOR_Pin_PWM  11            // пин выхода ШИМ на мотор ----- PORTPB2
#define Unbloking_Taim  (3*1000)     // время работы  Rele_Unbloking
#define LED_FLASH_RED 9              // мигалка ----- PORTPB0
#define BLINK_TIME 150               // скорость моргания красного светодиода
#define DEBOUNCE 100                 // задержка для антидребезга кнопки
#define MOTOR_TIMEOUT (45*1000)      // Время допустимой работы мотора в миллисекундах
boolean reverse_motor;               //переменная для реверса
boolean  Bloking ;                   //переменная разблокировки ворот
unsigned long StartTimer;            // счетчик времени для плавного пуска
int StartTimeStep = 1;               // Интервал изменения мощности двигателя, в мс
int StartPowerStep = 12;              // Один шаг изменения мощности двигателя
int MotorPower ;                     // Мощность двигателя
enum {STOP, CLOSE, CLOSED, OPEN, OPENED }; // возможные состояния системы
byte state;                          // текущее состояние системы
byte lastDir;                        // предыдущее направление движения ворот
byte nextDir;                        // следующее направление движения ворот
unsigned long startTime = 0;         //время начала  движения
long previousMillisA = 0;            //переменная времени
byte valA;                           //переменная счетчик
void setup() {
  // put your setup code here, to run once:
  pinMode (LED_FLASH_GREEN, OUTPUT);
  pinMode (LED_FLASH_RED, OUTPUT);
  pinMode (MOTOR_Pin_PWM, OUTPUT);
  pinMode(Swihc_Open_PIN, INPUT);
  pinMode(Swihc_Close_PIN, INPUT);
  pinMode(Fotoelement_PIN, INPUT);
  pinMode(Button_State_PIN, INPUT);
  pinMode(Close_Rele_Pin, OUTPUT);
  pinMode(Open_Rele_Pin, OUTPUT);
  pinMode(Power_TRANS_PIN, OUTPUT);
  pinMode(Rele_Unbloking_PIN, OUTPUT);
  state = STOP;                        // исходное состояние после включения питания
  lastDir = CLOSE;                     //последнее направление движения ворот
  nextDir = OPEN;                      // следующее направление движения ворот
  MotorPower = 0;                      // Начальная мощность мотора
}
void loop() {
  readButton();                       // опрос кнопки
  checkSwitches();                    // опрос концевиков, при коллизиях подавляет команду от кнопки
  ledsManager();                      // световая индикация
  motor();                            // управление двигателем
  reverse();                          //реверс после сработки фотоэлемента
  checkTimeout();                     //таймаут работы по времени
}
void checkTimeout()
{
  if ((state == OPEN || state == CLOSE) && ( (millis() - startTime) > MOTOR_TIMEOUT))
  {
    state = STOP;
    lastDir = state; // я бы добавил состояние "заклинило"
  }
}
void readButton()
{ static bool butt_flag = 0;
  static long past = 0;
  if ((millis() - past) < 20 ) return;
  if (digitalRead(Button_State_PIN) ) // если нажата кнопка
  {
    if (butt_flag) return;
    butt_flag = true;
    past = millis();
    if (state == STOP && lastDir == CLOSE  ) // даем команду на открытие
    {
      state = OPEN;
      startTime = millis();
      MotorPower = 120;                      // Начальная мощность мотора
    }
    else if (state == STOP && lastDir == OPEN) // даем команду на закрытие
    {
      state = CLOSE;
      startTime = millis();
      MotorPower = 120;                      // Начальная мощность мотора
    }
    else if (state == OPEN || state == CLOSE  ) // даем команду на остановку
    {
      lastDir = state;
      state = STOP;
      startTime = 0;
    }
    else if (state == OPENED && nextDir == CLOSE)
    {
      nextDir = CLOSE;
      state = nextDir;
      startTime = millis();
      MotorPower = 120;                      // Начальная мощность мотора
    }
    else if (state == CLOSED && nextDir == OPEN) {
      nextDir = OPEN;
      state = nextDir;
      startTime = millis();
      MotorPower = 120;                      // Начальная мощность мотора
    }
  }
  else {
    if (!butt_flag) return;
    butt_flag = false;
    past = millis();
  }
}
void checkSwitches()
{
  if (( digitalRead(Swihc_Open_PIN)) && state == OPEN) // полностью открытые ворота
  {
    nextDir = CLOSE;
    state = OPENED;
    reverse_motor = false;
  }
  else if ((  digitalRead(Swihc_Close_PIN)) && state == CLOSE)   // полностью закрытые ворота
  {
    nextDir = OPEN;
    state = CLOSED;
    Bloking = true;
  }
}
void motor()
{
  if (state == STOP) {
    MotorPower = 0;                      // Начальная мощность мотора
    analogWrite (MOTOR_Pin_PWM, MotorPower);   // Выключаем  ШИМ
    PORTB &= ~(1 << 4);//Power_TRANS_PIN    LOW
    PORTB &= ~(1 << 3); // Open_Rele_Pin 12 LOW
    PORTD &= ~(1 << 6); // Close_Rele_Pin 8 LOW
    PORTB &= ~(1 << 5);// Rele_Unbloking_PIN LOW
  }
  else  if (state == OPEN) {
    if (Bloking == true && ( digitalRead(Swihc_Close_PIN)) &&  ( (millis() - startTime) <=  Unbloking_Taim))
    {
      PORTB |= (1 << 5);// Rele_Unbloking_PIN HIGH
    } else if (Bloking == true &&  ( (millis() - startTime) > Unbloking_Taim ))
    {
      PORTB &= ~(1 << 5);// Rele_Unbloking_PIN LOW
      Bloking = false;
    }
    PORTB |= (1 << 4);//Power_TRANS_PIN HIGH
    PORTB |= (1 << 3); // Open_Rele_Pin 12 HIGH
    PORTD &= ~(1 << 6); // Close_Rele_Pin 8 LOW
    motorForvard();
  } else  if (state == CLOSE) {
    if (digitalRead(Fotoelement_PIN) ) {
      PORTB |= (1 << 4);//Power_TRANS_PIN HIGH
      PORTD |= (1 << 6); // Close_Rele_Pin 8 HIGH
      PORTB &= ~(1 << 3); // Open_Rele_Pin 12 LOW
      motorForvard();
    } else {
      state = STOP;
      reverse_motor = true;
    }
  }
  else  if (state == OPENED) {
    MotorPower = 0;                      // Начальная мощность мотора
    analogWrite (MOTOR_Pin_PWM, MotorPower);   // Выключаем  ШИМ
    PORTB &= ~(1 << 4);//Power_TRANS_PIN    LOW
    PORTB &= ~(1 << 5);// Rele_Unbloking_PIN LOW
    PORTB &= ~(1 << 3); // Open_Rele_Pin 12
    PORTD &= ~(1 << 6); // Close_Rele_Pin 8
  }
  else  if (state == CLOSED) {
    MotorPower = 0;                      // Начальная мощность мотора
    analogWrite (MOTOR_Pin_PWM, MotorPower);   // Выключаем  ШИМ
    PORTB &= ~(1 << 4);//Power_TRANS_PIN    LOW
    PORTB &= ~(1 << 5);// Rele_Unbloking_PIN LOW
    PORTB &= ~(1 << 3); // Open_Rele_Pin 12
    PORTD &= ~(1 << 6); // Close_Rele_Pin 8
  }
  //delay(DEBOUNCE); // простейший антидребезг кнопки
  _delay_ms(DEBOUNCE);
}
void ledsManager()
{
  boolean ledState;
  static unsigned long timestamp = millis();
  if (state == STOP )
  {
    //digitalWrite(LED_FLASH_RED, HIGH);
    PORTB  |= (1 << 0);
  }
  else if (state == CLOSED || state == OPENED) {
    //digitalWrite(LED_FLASH_GREEN, HIGH);
    //digitalWrite(LED_FLASH_RED, LOW);
    PORTB  |= (1 << 1);
    PORTB &= ~(1 << 0);
  }
  else  {
    if (millis() - timestamp > BLINK_TIME)
    {
      ledState = LOW;
      timestamp = millis();
    }
    else ledState = HIGH;
    //digitalWrite(LED_FLASH_GREEN, LOW);
    PORTB &= ~(1 << 1);
    digitalWrite(LED_FLASH_RED, ledState);
  }
}

void reverse() {
  if ( reverse_motor == true && state == STOP) {
    if (millis() - previousMillisA > 1000)
    {
      previousMillisA = millis();
      state = STOP;                       // работает счет
      valA++;
    }
    if (valA >= 4) //кол-во секунд((millis() -previousMillisA >1000) при достижении этого значения , мотор включается
    {
      nextDir = OPEN;
      state = nextDir;
      startTime = millis();
      MotorPower = 120;
      motorForvard();
      valA = 0;
    }
  }
}
void motorForvard() {
  if ((state == OPEN && MotorPower >= 120) || (state == CLOSE && MotorPower >= 120 ) )
    if (MotorPower < 255)
    {
      if ((millis() - StartTimer) >= StartTimeStep) // Проверяем, сколько прошло с последнего изменения скорости
        // если больше, чем заданный интервал – увеличим скорость еще на один шаг
      {
        MotorPower += StartPowerStep; // увеличение скорости
        analogWrite (MOTOR_Pin_PWM, MotorPower);   // На выводе  управляющий сигнал с новой скоростью
        StartTimer = millis(); // Начало нового шага
      }
    }
}

Был найден в сети. Примерно 70% переписал под себя.Много пришлось познать для этого, тяжело но интересно.

Green
Offline
Зарегистрирован: 01.10.2015

Даже не смотрел. Но. Я тут у себя делал фонарь с RC switch - там tiny45 едва хватило. Выебоны начинались из за нехватки RAM... Понятно, что можно поизгаляться, но только заради чего.

Foster777
Offline
Зарегистрирован: 20.07.2019

Код приемника выше,он на тиньке13  работает.

Скетч использует 774 байт (75%) памяти устройства. Всего доступно 1024 байт.

. Изначально было две команды.Один раз нажал кнопочку приходит код - ВКЛ,второй раз- ВЫКЛ.Как триггер.А мне нужно чтобы по нажатию кнопки пульта на выходе приемника однократно появлялась лог.1 и моргал светодиод. А оно моргает по несколько раз.

Green
Offline
Зарегистрирован: 01.10.2015

Я ж говорю. Дело не во Flash, дело в RAM.

Foster777
Offline
Зарегистрирован: 20.07.2019

Глобальные переменные используют 21 байт (32%) динамической памяти, оставляя 43 байт для локальных переменных. Максимум: 64 байт.

 

sanekovich
sanekovich аватар
Offline
Зарегистрирован: 14.04.2022

Всем привет. Нужна помощь .
Нужен считать коды с шлагбаума
doorhan .
И сделать чтоб его снова отправить .чтоб шлагбаум открывался. .
Есть какие ворианты. ?
Имеется передатчик и приемник от сигнализации СтарЛайн ну и Ардуино нано )

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

sanekovich шел бы ты отсюда, дядя

vrd
Offline
Зарегистрирован: 20.01.2022

В восьмом сообщении "Код приемника". В 26-й строке добавить "cameCode = 0;".