Passa al contingut principal

Clonar mando de un toldo Bauhaus E3430-GBR. Parte 2, Arduino.


Construcción del circuito con Arduino

En esta entrada continuaremos con el clonado del mando del toldo de Bauhaus, esta vez para crear el circuito con un arduino UNO o equivalente.

Partimos de que a partir de la captura de la señal con el sintonizador SDR habíamos conseguido entender un poco el protocolo del mando.
El mensaje que envía el mando está hecho por varios bloques que incluyen un preámbulo y el cuerpo del mensaje.
El preámbulo de sincronización se encuentra al inicio de cada bloque y dura aproximadamente 6300us. Su estructura aproximadamente tal como se puede ver en la siguiente imagen es de:
    • 4800us con emisión de señal.
    • 1550us de silencio.



A continuación del preámbulo viene el mensaje en sí mismo donde la pulsación de emisión de la señal es de unos 350us, aproximadamente, esto quiere decir que al menos el estado (en emisión o en silencio) dura 350us.
Podemos distinguir dos tipos de datos, el primer de unos 750us en emisión y 350us en silencio (110) que podíamos identificar como el valor lógico 1:
El segundo está completamente invertido al primero y son 350us en emisión junto con 750 de silencio (100) que podíamos identificar como al 0 lógico tal como se aprecia en las siguientes imágenes:
    110 → 1 lógico                100 → 0 lógico
  

Ya en el post anterior obtuvimos las capturas de las señales que corresponden a los 3 botones del mando, los mensajes de abrir, cerrar y parar, en formato binario y hexadecimal


  
  CLOSE  
type_a: 1011010100000110010111010101000100010001    B5065D5111
type_b: 1011010100000110010111010101000100011110    B5065D511E

4*(PREÁMBULO)B5065D5111+3*(PREÁMBULO)B5065D511E

OPEN  
type a: 1011010100000110010111010101000100110011    B5065D5133
type b: 1011010100000110010111010101000100111100    B5065D513C
4*(PREÁMBULO)B5065D5133+3*(PREÁMBULO)B5065D513C

STOP
type a: 1011010100000110010111010101000101010101 B5065D5155
3*(PREÁMBULO)B5065D5155
Ahora solo hay que reproducir estas señales mediante un Arduino (se puede emplear también un esp8266) y el transmisor de radio FS1000A.
Este transmisor es muy económico y lo podemos conseguir por aproximadamente 1€ en aliexpress o ebay.

El esquema propuesto incluye 3 pulsadores junto con sus resistencias en pull-down
También se puede añadir un led adicional y hacerlo parpadear al pulsar cualquier botón, sin embargo yo no lo he puesto para simplificar tanto el esquema como el sketch y he empleado el led interno.

El código para enviar los unos y ceros lógicos que hemos identificado con anterioridad es muy simple:

  #define TIME_SIGNAL 350
void rf433_one()
{
  digitalWrite(PIN_433_OUT, HIGH);
  delayMicroseconds(2 * TIME_SIGNAL);
  digitalWrite(PIN_433_OUT, LOW);
  delayMicroseconds(TIME_SIGNAL);
}
void rf433_cero()
{
  digitalWrite(PIN_433_OUT, HIGH);
  delayMicroseconds(TIME_SIGNAL);
  digitalWrite(PIN_433_OUT, LOW);
  delayMicroseconds(2 * TIME_SIGNAL);
}
Pero hace falta el preámbulo, si recordamos era 4800us en emisión y 1550us sin. El tiempo mínimo de una pulsación de señal es de 350us (no una pulsación en el mando del toldo).
4800/350 = 13,7
1550/350=4,4
En mi caso he hecho la prueba de generar el preámbulo redondeando los valores a 14 y 5:
 
  void rf433_preamble()
{
  digitalWrite(LED_BUILTIN, HIGH);
  digitalWrite(PIN_433_OUT, HIGH);
  delayMicroseconds(14 * TIME_SIGNAL);
  digitalWrite(PIN_433_OUT, LOW);
  delayMicroseconds(5 * TIME_SIGNAL);
  digitalWrite(LED_BUILTIN, LOW);
}

Ha funcionado correctamente, esto no quiere decir que sea válido para cualquier dispositivo, cada dispositivo en la banda de 433MHz es un mundo y emplean en muchos casos sus protocolos propios, pero como hemos visto los podemos obtener con el receptor SDR.
Adicionalmente he añadido un separador entre cada mensaje mensajes y una función que convierte el código hexadecimal en binario.

De forma que el sketch queda:


#define TIME_SIGNAL 350
#define PIN_433_OUT 11
#define PIN_OPEN 10
#define PIN_CLOSE 9
#define PIN_STOP 8

/*
 * Not used due to TIME_SIGNAL*14 also works  * 
 * if not, replace these values in rf433_preamble function * 
#define PREAMBLE_TIME_HIGH 4750
#define PREAMBLE_TIME_LOW 1500
*/

#define SEPARATION_TIME_LOW 350
void rf433_preamble();
void rf433_separator();
void rf433_one();
void rf433_zero();
void rf433_send();
void open_awning();
void close_awning();
void stop_awning();

byte open_signal_a[] = {0xB5, 0x06, 0x5D, 0x51, 0x33};
byte open_signal_b[] = {0xB5, 0x06, 0x5D, 0x51, 0x3C};

byte stop_signal_a[] = {0xB5, 0x06, 0x5D, 0x51, 0x55};

byte close_signal_a[] = {0xB5, 0x06, 0x5D, 0x51, 0x11};
byte close_signal_b[] = {0xB5, 0x06, 0x5D, 0x51, 0x1E};

int openAwning = 0;
int closeAwning = 0;
int stopAwning = 0;

void rf433_preamble()
{
  digitalWrite(LED_BUILTIN, HIGH);
  digitalWrite(PIN_433_OUT, HIGH);
  delayMicroseconds(14 * TIME_SIGNAL);
  digitalWrite(PIN_433_OUT, LOW);
  delayMicroseconds(5 * TIME_SIGNAL);
  digitalWrite(LED_BUILTIN, LOW);
}
void rf433_separator()
{
  digitalWrite(PIN_433_OUT, LOW);
  delayMicroseconds(SEPARATION_TIME_LOW);
}
void rf433_one()
{
  digitalWrite(PIN_433_OUT, HIGH);
  delayMicroseconds(2 * TIME_SIGNAL);
  digitalWrite(PIN_433_OUT, LOW);
  delayMicroseconds(TIME_SIGNAL);
}
void rf433_zero()
{
  digitalWrite(PIN_433_OUT, HIGH);
  delayMicroseconds(TIME_SIGNAL);
  digitalWrite(PIN_433_OUT, LOW);
  delayMicroseconds(2 * TIME_SIGNAL);
}

void close_awning()
{
  rf433_preamble();
  for (byte i = 0; i < 4; i++)
  {
    rf433_send(close_signal_a, 5);
    rf433_separator();
  }
  for (byte i = 0; i < 3; i++)
  {
    rf433_send(close_signal_b, 5);
    rf433_separator();
  }

  delay(10);
}

void open_awning()
{
  rf433_preamble();
  for (byte i = 0; i < 4; i++)
  {
    rf433_send(open_signal_a, 5);
    rf433_separator();
  }
  for (byte i = 0; i < 3; i++)
  {
    rf433_send(open_signal_b, 5);
    rf433_separator();
  }

  delay(10);
}

void stop_awning()
{
  rf433_preamble();
  for (byte i = 0; i < 3; i++)
  {
    rf433_send(stop_signal_a, 5);
    rf433_separator();
  }

  delay(10);
}

void setup()
{
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(PIN_433_OUT, OUTPUT);
  pinMode(PIN_OPEN, INPUT);
  pinMode(PIN_CLOSE, INPUT);
  pinMode(PIN_STOP, INPUT);

  Serial.println("Hello Awning\n");
}
void loop()
{

  openAwning = digitalRead(PIN_OPEN);
  closeAwning = digitalRead(PIN_CLOSE);
  stopAwning = digitalRead(PIN_STOP);

  if (openAwning == HIGH)
  {
    open_awning();
    Serial.println("OPEN");
  }
  else if (closeAwning == HIGH)
  {
    close_awning();
    Serial.println("CLOSE");

  }
  else if (stopAwning == HIGH)
  {
    stop_awning();
    Serial.println("STOP");

  }
}

/* 
Convert hex to bin and use rf433_one, rf433_zero to send data
*/
void rf433_send(byte *buffer, byte bufferSize)
{
  for (byte i = 0; i < bufferSize; i++)
  {
    byte n = buffer[i];
    for (int i = 7; i >= 0; i--)
    {
      if ((n >> i) & 0X01)
      {
        rf433_one();
      }
      else
      {
        rf433_zero();
      }
    }
  }
}
  
El próximo paso es emplear un Wemos D1 mini e integrarlo con el ESPHome y Homeassistant, pero esto ya será otra historia.

 

Comentaris