Open guyfawcus opened 4 years ago
Hi there by the way! If your still here at least :laughing: sorry I'm a bit late to the game!
Here's a start for reversing the RX protocol:
N.B. The spacing and pipes are just there for emphasis. All of the pairs are hex and are grouped every 3 bytes (84 xx xx
) for clarity.
L - ON - 84 20 00 84 20 00 84 28 00 84 28 00
L - OFF - 84 28 00 84 08 00 84 08 00 84 00 00
R - ON - 84 08 00 84 08 00 84 28 00 84 28 00
R - OFF - 84 28 00 84 20 00 84 20 00 84 00 00
1 - ON - 84 02 00 84 02 00
1 - OFF - 84 02 00 84 00 00
2 - ON - 84 00 20 84 00 20
2 - OFF - 84 00 20 84 00 00
3 - ON - 84 00 08 84 00 08
3 - OFF - 84 00 08 84 00 00
4 - ON - 84 00 02 84 00 02
4 - OFF - 84 00 02 84 00 00
L SOLO ON - 84 28 00 |84 68 00 84 68 00 |84 78 00 84 78 00 84 78 00 84 78 00 84 78 00 84 78 00 84 78 00 84 78 00 84 78 00
L SOLO OFF - 84 38 00 |84 18 00 |84 38 00 84 38 00 84 38 00 |84 28 00 84 28 00 84 28 00 84 28 00 84 28 00 84 28 00 84 28 00 84 28 00 84 28 00
R SOLO ON - 84 28 00 |84 68 00 84 68 00 |84 78 00 84 78 00 84 78 00 84 78 00 84 78 00 84 78 00 84 78 00 84 78 00 84 78 00
R SOLO OFF - 84 68 00 |84 60 00 84 60 00 |84 20 00 |84 28 00 84 28 00 84 28 00 84 28 00 84 28 00 84 28 00 84 28 00 84 28 00 84 28 00 84 28 00
1 SOLO ON - 84 02 00 84 02 00 84 02 00 84 02 00 84 02 00 |84 06 00 84 06 00 84 06 00 84 06 00 84 06 00 84 06 00 84 06 00
1 SOLO OFF - 84 06 00 84 06 00 84 06 00 84 06 00 84 06 00 |84 02 00 84 02 00 84 02 00 84 02 00 84 02 00 84 02 00 84 02 00
2 SOLO ON - 84 00 20 84 00 20 84 00 20 84 00 20 84 00 20 84 00 20 84 00 20 |84 00 60 84 00 60 84 00 60 84 00 60 84 00 60
2 SOLO OFF - 84 00 60 84 00 60 84 00 60 84 00 60 84 00 60 84 00 60 84 00 60 |84 00 20 84 00 20 84 00 20 84 00 20 84 00 20
3 SOLO ON - 84 00 08 84 00 08 84 00 08 84 00 08 84 00 08 84 00 08 84 00 08 84 00 08 84 00 08 |84 00 18 84 00 18 84 00 18
3 SOLO OFF - 84 00 18 84 00 18 84 00 18 84 00 18 84 00 18 84 00 18 84 00 18 84 00 18 84 00 18 |84 00 08 84 00 08 84 00 08
4 SOLO ON - 84 00 02 84 00 02 84 00 02 84 00 02 84 00 02 84 00 02 84 00 02 84 00 02 84 00 02 84 00 02 84 00 02 |84 00 06
4 SOLO OFF - 84 00 06 84 00 06 84 00 06 84 00 06 84 00 06 84 00 06 84 00 06 84 00 06 84 00 06 84 00 06 84 00 06 |84 00 02
P.S. This should all be correct but some of this was hand transcribed from my scopes decoder because I'm currently working through an issue with sigrok and my DS1054z :roll_eyes: .
P.P.S. Just pasting this here because I can't seem to work it out yet. It just seems so convoluted, especially considering how simple the TX commands are and how easy they were to figure out.
It's a ̶U̶n̶i̶x̶ bit manipulation system, I know this!
As I suspected, like the TX commands, the RX communication is based on bit manipulation. Haven't quite got my head around some of the whys of the seemingly superfluous RX data yet, but I have confirmed that if you hook up a 3.3V TTL serial connection to the remote and use the following table, you can light up whatever LEDs you want! :tada:
Make sure it's 3.3V logic, and unplug the recorder. This is only for testing the remote!
0x82
(10000010
)record
and play/pause
buttons, you can use any of the following colours:
For example, to light up the LEDs for channels 1-4 in red using Python:
import serial
import time
s = serial.Serial('/dev/ttyUSB0')
s.baudrate = 2400
# Initialise the connection (only have to do this once)
s.write(bytes([0b10000010]))
time.sleep(0.5)
# Now send the data
s.write(bytes([0b10000100, 0b00000010, 0b00101010]))
Whoa; thank you very much for your feedback! I haven't poked at this project or my H6 in a good while, but this is making it very tempting to say hi to it again...
Could I tempt you even more with this?.. Zoom-H6-OLA-bridge
You can now control the LEDs on the remote with lighting control software or one of these: :rofl:
I think I need to get back on track...
Hi guys!
Any news about this? I'm also really interested in being able to control my Zoom H6 from my computer. I've connected it using an FTDI USB adapter, and I've tried sending some codes to it, but no luck. Also, I don't get any serial activity from it when I start recording or enable a channel, which is the strangest part.
@guyfawcus, were you able to find something else?
@mattogodoy - Sorry dude, got a little distracted with another project (yet again!)
I stopped after getting the remote to light up like a Christmas tree and never actually implemented any control to the recorder (despite that being the main goal in all of this :roll_eyes: )
I'll take another look at this tonight and hopefully get you some code for tomorrow :ok_hand:
In the mean time, I've got a few questions to make sure that your on the right track:
If you're talking to the recorder, don't hook up the 3.3V pin. You should only need GND/TX/RX. It'd probably be fine but I wouldn't chance it because it's unnecessary and could lead to a bad day, especially if the adapter is in 5V mode!.
Just had a thought - I seem to remember that unless you send a zeroed byte (0x00) to the recorder it won't send any commands back. This initialisation is usually taken care of by the remote. Read though this post again, specifically the protocol section, that should cover most of it.
I know how tricky this sort of stuff can be if you don't have things like a scope and a remote to double check and test things but when boiled down it should be a pretty simple thing to get going, so after I write some docs you shouldn't have any issues (just try not to damage anything in the meantime :stuck_out_tongue_winking_eye:)
Thanks a lot for your reply! If you get to make it work you'll make me a really happy man 😃
I'll answer your questions in order:
Here's a sample of the code I'm using:
import serial
import time
s = serial.Serial('/dev/cu.usbserial-alcdut1', 2400, parity='N', stopbits=1)
# Create a REC button press command
rec_packet = bytearray()
rec_packet.append(0x81)
rec_packet.append(0x00)
# Create a button release command
release_packet = bytearray()
release_packet.append(0x80)
release_packet.append(0x00)
# Send REC, wait for a bit and release
s.write(rec_packet)
time.sleep(0.1)
s.write(release_packet)
# Close serial connection
time.sleep(0.1)
s.close()
I did not know about the initialisation byte, I'll take a look at the link you posted.
If you manage to make it work please let me know! I'll report back if a get something.
Thanks again for the info 💪
No problem at all, I love this stuff!
Cheers for that, looks like you're all set :+1:
The problem was indeed the handshake, the recorder won't do anything or send any data without it. I need to do a bit more testing but I got it to work so I thought I'd send over what I had so that you can get cracking.
import serial
import time
s = serial.Serial('/dev/ttyUSB0') s.baudrate = 2400 s.timeout = 0.032
* Initialise the connection with the handshake
``` python
handshake_complete = False
while handshake_complete != True:
s.write(b'\00')
if s.read(1) == b'\x82':
s.write(b'\xC2')
if s.read(1) == b'\x83':
s.write(b'\xE1\x31\x2E\x30\x30')
if s.read(1) == b'\x80':
s.write(b'\xA1')
if s.read(1) == b'\x81':
s.write(b'\x80\x80')
handshake_complete = True
# Create a REC button press command
rec_packet = bytearray()
rec_packet.append(0x81)
rec_packet.append(0x00)
release_packet = bytearray() release_packet.append(0x80) release_packet.append(0x00)
s.write(rec_packet) time.sleep(0.1) s.write(release_packet)
I'll try and get round to coding something to check the reply's using some stuff I wrote a while ago to light up the LEDs on the remote[1], but in the meantime I've verified that all of the bytes that I reverse engineered initially[2] are correct:
stop = bytearray([0b10010000, 0b00000000])
forward = bytearray([0b10001000, 0b00000000])
reverse = bytearray([0b10000100, 0b00000000])
play_pause = bytearray([0b10000010, 0b00000000])
record = bytearray([0b10000001, 0b00000000])
vol_up = bytearray([0b10000000, 0b10000000])
vol_down = bytearray([0b10000000, 0b01000000])
ch4 = bytearray([0b10000000, 0b00100000])
ch3 = bytearray([0b10000000, 0b00010000])
ch2 = bytearray([0b10000000, 0b00001000])
ch1 = bytearray([0b10000000, 0b00000100])
right = bytearray([0b10000000, 0b00000010])
left = bytearray([0b10000000, 0b00000001])
release_button = bytearray([0b10000000, 0b00000000])
def send(command):
s.write(command)
s.write(release_button)
# send(record)
Ha! I was just trying when you posted the last message. IT WORKS!
The next step is to integrate this into a microcontroller, but having the logic and the commands it should not be that hard.
Thanks a lot for your help! You rock 🤘
Glad to hear you got it working! Can't wait to read about it on your blog (love the airsoft bomb :stuck_out_tongue_winking_eye: ).
Just installed hacker-sounds as well by the way... hilarious :rofl: not sure how happy my other half is going to be though considering we're both working from home now and sitting at the same table!
Hahaha I'm glad you like it. It makes you 200% more productive :D
Here's some code* that I've been using to check things out. It's far from perfect but it has proved useful, it allows you to send commands and read the state back. Hope it's useful for you too! :man_technologist:
Cool! That is in fact really useful to me. I'll try it tomorrow. Thanks a lot!
No worries :metal: just added another little helper function by the way, it allows you to press multiple buttons simultaneously.
Ooh, and just fixed a bug with displaying solo messages.
A couple of small notes for things I've come across:
To solo a channel you need to 'hold' the button for at least 1.5 seconds (1500ms). You don't need to wait until you it sends a message back with the solo state (that message is sent 1.5 seconds after you 'click' the button).
A delay of at least 0.54 seconds (540ms) is required between repeatedly pressing buttons 1 + 2 or 3 + 4. Any less and interprets it as a command to pair up the channels.
That's great to know. Thanks for sharing!
Hello!
Following the discussion here I was able to start and stop recording on my Zoom H5 using a STM32 Nucleo Board (042K6)
Seems like Zoom H5 is skipping one step of the handshake though
if s.read(1) == b'\x80':
s.write(b'\xA1')
I made a simple code for now which sends start stop record with push of a button. I needed to create a simple debounce filter so any other button press in 1 second is ignored.
Next step I will try to trigger this with the flashing LED of my GO-PRO so I can record both video and audio just by using the GoPro remote!
The code is as follows:
#include "mbed.h"
InterruptIn btn(PA_12);
Serial serial(PA_9, PA_10); // tx, rx
DigitalOut myled(LED1);
char request=0;
static void toggleLed()
{
if(myled==1)
{
myled = 0;
}
else
{
myled = 1;
}
}
static void onButtonPress()
{
/*__disable_irq();
toggleLed();
char command=0x81;
//device.printf("%x",command);
serial.putc(command);
command=0x00;
serial.putc(command);
wait(0.2); // 200 ms
command=0x80;
//device.printf("%x",command);
serial.putc(command);
command=0x00;
serial.putc(command);
wait(1);
__enable_irq();*/
request=1;
}
static void sendrecord()
{
char command=0x81;
//device.printf("%x",command);
serial.putc(command);
command=0x00;
serial.putc(command);
wait(0.2); // 200 ms
command=0x80;
//device.printf("%x",command);
serial.putc(command);
command=0x00;
serial.putc(command);
wait(1);
}
int main() {
serial.baud(2400);
btn.fall(&onButtonPress);
char handshake_complete=0;
char rcv;
wait(1);
toggleLed();
wait(1);
toggleLed();
wait(1);
toggleLed();
while (handshake_complete != 1)
{
serial.putc(0x00);
rcv=serial.getc();
if(rcv==0x82)
{
serial.putc(0xC2);
rcv=serial.getc();
if(rcv==0x83)
{
serial.putc(0xE1);
serial.putc(0x31);
serial.putc(0x2E);
serial.putc(0x30);
serial.putc(0x30);
rcv=serial.getc();
if(rcv==0x81)
{
serial.putc(0x80);
serial.putc(0x80);
handshake_complete=1;
}
}
}
wait(1);
toggleLed();
}
while(1)
{
wait(0.2); // 200 ms
toggleLed();
if(request==1)
{
sendrecord();
request=0;
}
}
}
Thanks a lot!
Your work helped me immensely while I've been trying to build an Arduino-based controller for my Zoom H5. I intended to build a timer-based recording system (think of it like audio time-lapse, or an audio data-logger) but there's a hitch: The Zoom H5 can only record 500 files per folder. It won't automatically roll over to the next folder, so you must manually select a new folder in the menu every 500 files if you want to keep it going. Just mentioning it here in case it trips up somebody else.
Pinout
(Colours are of the enameled wires in the extension cable that is part of the APH-6 accessory pack)
(Image from Blueduino-RC4)
Signalling
Signalling is 3.3V TTL serial at 2,400 bit/s (baud) 8N1 (8 Data bits, No parity and 1 stop bit) LSB (Least Significant Bit first)
Protocol
On boot, the remote sends a zeroed byte (0x00) every 32ms until it receives a 0x82 (28.3ms between the end of one byte and the start of the next)
The handshake goes like this (including the 'last' zeored byte and the first reply):
10000000 00000000
)Multiple button can be sent at a time. however, with 1+3 and 2+4, if both are pressed at the same time, the second is ignored, (This is likely a hardware limitation because of a matrix keyboard, not 100% though)
First byte
Second byte
For example, pressing stop will transmit:
10010000 00000000
followed by:10000000 00000000
and pressing 1 and 2 will transmit:
10000000 00001100
followed by:10000000 00000000
Power