Thomas Lochmatter · LaTeX to SVG · Secret Sharing · RGB/xy · NTC · PDF · QR · Unicode

Controlling Gaviota Cross Box Motors from a Computer

Gaviota sells motors for blinds and shutters. One of their product lines — the Cross Box series — are controlled using a wireless remote:

Gaviota Cross Box Motor with Remote Control

These motors are very easy to install: they are simply connected to the mains (240 V). The rest is done using one of their battery-powered remotes, which come in various shapes and flavors.

433 MHz radio communication

Remote and motor communicate using radio waves in the 433 MHz band. More precisely, they use on-off keying (OOK) on a 433.92 MHz carrier, a modulation scheme used by many wireless garage door openers and "smart" power plugs.

When pressing one of the buttons on the remote, the remote sends a datagram to the motor. Such a transmission has the following structure:

Gaviota Datagram in the air (physical layer)

Every transmission starts with a 4900 µs high pulse (ON), followed by a low pulse (OFF) of about 1550 µs. Each spike following that start sequence represents one bit. A short pulse followed by a long pause is a "0", and a long pulse followed by a short pause a "1":

Signal wave of one bit

Every bit takes 1120 µs to transmit, with the short part taking about one third of that (373 µs). Hence, every bit starts with a high signal, and ends with a low signal, allowing the receiver to resynchronize. The actual information (bit value) is in the center of the signal.

A datagram takes 51.25 ms to transmit. The receiver on the motor is quite forgiving, however: the datagram can be sent up to 20% slower (1350 µs/bit) or 15% faster (945 µs/bit).

Datagrams

The 40 bits included in the datagram have the following structure:

Gaviota Datagram

The ID is probably just a random number. We tested a few IDs, and they all worked fine.

CH denotes the channel, and corresponds to the number displayed on the remote (0 to 15). The most significant bit is sent first. According to the documentation of the remote, channel 0 is the group channel, which acts upon all motors connected to this remote.

The command number is tied to the buttons on the remote:

Button, action Command Bits
Up 17 0001 0001
Up released 30 0001 1110
Down 51 0011 0011
Down released 60 0011 1100
Stop 85 0101 0101
M 193 1100 0001
P2 204 1100 1100

Again, the most significant bit is sent first.

When pressing the up or down button, the corresponding command (17 or 51) is sent as long as the key is pressed. Once the button is released, 6 release datagrams (30 or 60) are sent.

The stop button sends datagrams with command 85 as long as the button remains pressed.

The P2 button is used for connecting motors with remotes (teach-in). Pressing that button sends 4 datagrams with command 204.

Multiple datagrams are sent with a gap of about 8 ms. That corresponds to a rate of approximately 17 datagrams per second. During that time, the radio band is almost fully used. Two remotes used at the same will interfere with each other.

All communication is unidirectional from the remote to the motor. The motor does not send anything back to the remote.

Sending datagrams from a computer

Using a microcontroller and a RF 433 MHz tranceiver module, the above datagrams can be sent from a computer. Strictly speaking, a transmitter module is sufficient.

The following code sends a few datagrams from an Arduino board:

		// HIDE
		#include <Arduino.h>

		// SHOW
		// Data pin of the transmitter
		int outPin = 2;

		static void sendHighLow(int high, int low) {
			digitalWrite(outPin, HIGH);
			delayMicroseconds(high);
			digitalWrite(outPin, LOW);
			delayMicroseconds(low);
		}

		static void sendBit(int bit) {
			if (bit) {
				sendHighLow(747 - 20, 373 - 6);
			} else {
				sendHighLow(373 - 20, 747 - 6);
			}
		}

		static void sendGaviotaCommand(uint32_t id, uint8_t channel, uint8_t command) {
			// Start
			sendHighLow(4900, 1550);

			// ID (28 bits)
			uint32_t idMask = 0x08000000;
			while (idMask) {
				sendBit(id & idMask ? 1 : 0);
				idMask >>= 1;
			}

			// Channel (4 bits)
			uint8_t channelMask = 0x08;
			while (channelMask) {
				sendBit(channel & channelMask);
				channelMask >>= 1;
			}

			// Command (8 bits)
			uint8_t commandMask = 0x80;
			while (commandMask) {
				sendBit(command & commandMask);
				commandMask >>= 1;
			}
		}

		void setup() {
			pinMode(outPin, OUTPUT);

			// Send command 17 (up)
			sendGaviotaCommand(54321098, 1, 17);
			delay(8);
			sendGaviotaCommand(54321098, 1, 17);

			// Wait for 3 seconds
			delay(3000);

			// Send command 85 (stop)
			sendGaviotaCommand(54321098, 1, 85);
			delay(8);
			sendGaviotaCommand(54321098, 1, 85);
		}

		void loop() {
		}
	

The transmitter is connected to D2. The signals are not very accurate, since the Arduino library regularly runs the timer0 interrupt, which inserts delays of 5-10 µs. The receiver on the motor still decodes the datagrams properly.