Skip to content

Jackson PT9723 remote power control and Arduino

Jackson blister pack
The Jack­son PT9723 is yet another 433MHz remote power con­trol sys­tem. I picked mine up on sale from Office­works last month, who don’t seem to sell them any more. But they’re still read­ily avail­able online for a fairly mod­est price.

I bought it with the inten­tion of con­trolling it with an Ardu­ino. How­ever, inter­fa­cing with it proved to be a little more dif­fi­cult than most other sys­tems around, and nobody else seems to have done it yet. So here’s how I man­aged it.

About the remote

The remote handles four sep­ar­ate chan­nels. On the out­side, rather than but­tons that toggle each chan­nel on or off, the remote has sep­ar­ate on and off but­tons for each chan­nel, as well as a 9th but­ton to turn all chan­nels off. On the inside there’s two main parts that we care about.

  • A Hol­tek 7130A-1 power reg­u­lator. This takes the 12V from the bat­tery and out­puts 3V (at up to 30mA) to power the rest of the cir­cuit. After acci­dent­ally hook­ing this up to my bench sup­ply with the polar­ity reversed, I can con­firm that these oper­ate using really foul-smelling smoke. Luck­ily we won’t be requir­ing it any more.
  • A Hol­tek HT46R01T3. This chip com­bines a small MCU with a 433MHz trans­mit­ter. The data sheet spe­cifies an oper­at­ing voltage of 2V-3.6V, so it’s trivial to power from the 3.3V rail on an Arduino.

Six of the GPIOs from the HT46R01T3 are used. Each but­ton shorts a pair of these GPIOs together to tell the MCU to trans­mit a com­mand. So to talk to an ardu­ino we break out six GPIO pins, plus two more wires to power the remote.

Parts

As well as an Ardu­ino, we use:

  • A shift register. I used a Freet­ron­ics EXPAND shift register mod­ule.
  • 8x NPN tran­sist­ors. BC549s worked for me. A BC547 or any other equi­val­ent should be fine.
  • 8x 150kΩ resistors.
  • Some 8-strand rib­bon cable, in addi­tion to a hand­ful of other hookup wire.

Hard­ware hacking

Each com­mand is triggered by short­ing two GPIO pins together. The pins used, and the res­ult­ing com­mand, look like:

Pins16213
14Out­let 1 OnOut­let 2 OffAll Out­lets Off
15Out­let 1 OffOut­let 3 OnOut­let 4 On
3Out­let 2 OnOut­let 4 OffOut­let 4 Off

Internal wiring connections for remote

To start with, we take a length of 8-strand rib­bon cable, and solder it on to the remote PCB. For power, use the neg­at­ive bat­tery ter­minal, and the far right (from the back) pin of the power reg­u­lator. For the GPIO pins, I used a con­tinu­ity meter to trace them to a con­veni­ent solder pad on one of the push buttons.

For my remote, these are how the dif­fer­ent wires wound up being connected:

Red+3.3V
BrownGND
GreyPin 2
PurplePin 3
BluePin 13
GreenPin 14
Yel­lowPin 15
OrangePin 16

Using out­put 7 on the shift register to issue a com­mand through the remote.

We use a sep­ar­ate tran­sistor to activ­ate each com­mand, omit­ting the “all out­puts off” com­mand. Each out­put from the shift register is con­nec­ted to a 150kΩ res­istor, which is then con­nec­ted to the base of an NPN tran­sistor. Two GPIO pins are then con­nec­ted to the col­lector and emit­ter pins of the tran­sistor. To issue the “Out­let 1 On” com­mand, con­nect GPIO pins 14 and 16. It doesn’t seem to mat­ter which way around these are con­nec­ted to the tran­sistor — I tested both ori­ent­a­tions and they seemed to work.

We need eight of these switches. I tested each com­mand on a bread­board, and then indi­vidu­ally after assem­bling them on a pro­to­type board. Once they’re assembled they’re con­nec­ted to the out­puts from the shift register. My code uses “Out­let 1 On” hooked to out­put H, “Out­let 1 Off” to out­put G, “Out­let 2 On” to out­put F and so on. Because I assembled it upside down. :-(

Con­nect the +ve wire from the remote to the 3.3V power pin on the Ardu­ino, and the ground wire from the remote to one of the ground pins on the Arduino.

Finally, the shift register is con­nec­ted to the Ardu­ino. For the EXPAND module:

  • Con­nect Vcc and Reset pins to the 5V sup­ply on the Arduino.
  • Con­nect GND and Out­put Enable pins to the GND pin on the Arduino.
  • Con­nect Clock to digital pin 5 on the Arduino.
  • Con­nect Latch to digital pin 6 on the Arduino.
  • Con­nect Serial In to digital pin 7 on the Arduino.

It gets a little bit cramped, but I was able to fit the EXPAND mod­ule and all other com­pon­ents on to a Freet­ron­ics Pro­toShield Short, with enough room left over on the right hand side for a couple more relay drivers that I am avoid­ing dis­cuss­ing in this post.

Soft­ware hacking

To trans­mit a com­mand we have to sim­u­late a but­ton press:

  • Send a value to the shift register turn­ing on the appro­pri­ate register output.
  • Delay briefly. 500ms works well to just issue a com­mand. If you want to use the ardu­ino to pro­gram out­lets then closer to 2000ms would be needed.
  • Send a 0 to the shift register to turn off all register outputs.

The below sample sketch listens for key­strokes entered on the serial con­sole, and sends the asso­ci­ated com­mand. Train a couple of out­lets to the remote, load the sketch, open a serial con­sole (make sure the “no line end­ing” option is set), and then if you’re any­thing like me spend half an hour typ­ing on the key­board and gig­gling at the little LEDs turn­ing on and off.

/* RemoteDemo
   Demo sketch for Jackson remote power control.

   Hardware:
   A shift register connected to pins 5, 6, and 7.
   Outputs are wired as:
     A: 4off
     B: 4on
     C: 3off
     D: 3on
     E: 2off
     F: 2on
     G: 1off
     H: 1on

   Run the sketch, and open the Serial Monitor in the Arduino IDE.
   Typing a letter between a-h will send the associated command.
*/
// IO pins
const int dataPin = 7;
const int latchPin = 6;
const int clockPin = 5;

boolean cmdEnabled = false; // true if we're sending a command
long cmdTimer = 0;          // track how long we're sending command
int inByte = 0;             // incoming serial byte

void sendCmdOn(int cmd) {
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, cmd);
  digitalWrite(latchPin, HIGH);
  cmdEnabled = true;
  cmdTimer = millis() + 500;
}

void sendCmdOff() {
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, 0);
  digitalWrite(latchPin, HIGH);
  cmdEnabled = false;
}

void setup() {
  pinMode(dataPin, OUTPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);

  // Flush the expand module
  sendCmdOff();

  Serial.begin(9600);
}

void loop() {
  // If there's a serial character waiting, parse it
  // and send the appropriate command.
  if (Serial.available() > 0) {
    inByte = char(Serial.read());
    switch (inByte) {
    case 'h':
      Serial.println("Turning on Outlet 1");
      sendCmdOn(128);
      break;
    case 'g':
      Serial.println("Turning off Outlet 1");
      sendCmdOn(64);
      break;
    case 'f':
      Serial.println("Turning on Outlet 2");
      sendCmdOn(32);
      break;
    case 'e':
      Serial.println("Turning off Outlet 2");
      sendCmdOn(16);
      break;
    case 'd':
      Serial.println("Turning on Outlet 3");
      sendCmdOn(8);
      break;
    case 'c':
      Serial.println("Turning off Outlet 3");
      sendCmdOn(4);
      break;
    case 'b':
      Serial.println("Turning on Outlet 4");
      sendCmdOn(2);
      break;
    case 'a':
      Serial.println("Turning off Outlet 4");
      sendCmdOn(1);
      break;
    default:
      Serial.println("Invalid command received");
    }
  }

  // If we've exceeded the timer, stop sending a command.
  if (cmdEnabled && cmdTimer < millis()) {
    Serial.println("Releasing button");
    sendCmdOff();
  }
}