I have recently been wanting to play with LoRa radios because reasons. This gives me a way of sending short messages between devices using a lightweight protocol with a range of a couple of kilometres on a bad day. I ended up picking up a Challenger 2040 LoRa manufactured by iLabs from The PiHut, mostly because all the others were out of stock. I then spent three days just getting the radio to initialize in my code. Challenger RP2040 LoRa
As the Challenger 2040 LoRa has a lot of unhelpful documentation, this is a practical getting started guide using Platform IO, an alternative to the Arduino IDE, in Visual Studio Code on Windows for this board. Some familiarity with VS Code and Platform IO is assumed.
Installing RP2040 Support for Platform IO
If you have used the Pico 2040 before then you have probably done this already, but if not here is a summary for Windows users – this is for a new installation. The full instructions are on readthedocs.io, if you have it installed already and see the depreciation warning, check the full instructions:
Open an Administrator Console/Terminal (Terminal > Right Mouse Click and choose Run As Administrator), then:
Enable long paths in git: git config ——system core.longpaths true
Adding to Platform IO
Now load up VS Code, and in Platform IO create new project, Give it a name (rp2040test) and select Raspberry Pi Pico as the board and Arduino as the framework.
Pi Pico – Platform IO Selection
Click Finish and let it do its thing. This will give us a platformio.ini file to edit.
When you save the file it takes a few minutes to automatically add the RP2040 SDK and long list of development boards including the Challenger 2040 LoRa to those available in Platform IO. You can now create a new project and choose the Challenger 2040 LoRa from the list of boards, which will give you this default platformio.ini:
default challenger platformio.ini
INI
1
2
3
4
[env:challenger_2040_lora]
platform=raspberrypi
board=challenger_2040_lora
framework=arduino
but I prefer to use the one below.
Initializing the LoRa Radio
This is the part that took me the most time to get working, here is the cheat-sheet. Set platformio.ini as:
This is a modified version of the LoRaDumpRegisters.ino example just to show it working. The changes are to have it selecting SPI1 and setting the correct pins for the radio. Remember to set the correct frequency for your region:
This is more of a nostalgia trip / messing about thing rather than a serious use of Voice over IP (VoIP). The Cisco SPA122 ATA with Router (Analog Telephone Adapter) is a small box that allows old analog phones to be connected to a VoIP network. At the time of writing Cisco no longer manufactures these and they are currently in an end of life plan. Cisco SPA122 ATA with Router
I am setting this up to use two handsets that can be used to call each other through the SPA122. I don’t have a VoIP service here and don’t have need for one. Later, I will be setting up a couple of modems and using them for a dialup connection, in this part I will be going through the setup and configuration of the SPA122. SPA122 And Two Telephones
You will need:
An SPA122 – I got mine from eBay, check that you are purchasing a vanilla model, rather than one that has been configured by a carrier, be wary if it has any other logos printed on it as it may be locked to that carrier.
A 5V power supply, this must be capable of providing at least 2A.
Two telephones – I got these from the Charity Shop, get ones with tone dialing (DTMF), pulse dialing will not work – I’ve also found using better quality phones made in the early 2000’s work better than cheap new ones, I ended up with BT Decor 1100 and BT Decor 1200 phones.
Two adapters to convert the UK phone plug to RJ11 sockets on the SPA122. Search for “RJ11 to BT Socket” on eBay or Amazon, these are cheap.
A wired LAN connection to your network.
A computer, preferably with WiFi as well as a Wired Connection, I used a Raspberry Pi 4.
RJ11 to BT Socket Connector
Default Settings
IP Address: 192.168.15.1 – with a computer plugged into the yellow ethernet port
Username: admin
Password: admin
Resetting the SPA122 and Gaining Access
With a network lead from your computer to the yellow ethernet port on the SPA122 open your web browser and try the address 192.168.1.15. You should now see the login screen, try the login details above.
That probably didn’t work. To reset to factory default settings use a paperclip on the rear panel reset button. With the unit powered on, use the end of a paperclip to press into the red hole marked RESET located on the bottom-left side of the back panel of the SPA122. Press and hold for at least a full 20 seconds and the Power LED will start to blink when the restore process begins, this will take around two minutes to complete. Now try logging in as admin again.
Once logged in, change the admin password to something else, if left at the default it will refuse to work.
If you are really unlucky the reset button may have been disabled in the firmware. At this stage I don’t know what to do if this has happened.
You can also configure the device by pressing the star button on your handset four times (****) but that way madness lies.
Upgrade the Firmware
At time of writing, the firmware version available from Cisco is Release 1.4.1 SR5. The update appears to be fixing a variety of security problems. You can find the current Firmware Version in Status > System Information.
Updating is straight forward. Download the file, and unzip it to extract the Payton_1.4.1_SR5_101419_1250_pfmwr.bin file, then in the SPA122 pages in your web browser go to Administration > Firmware Upgrade and follow the instructions. Everything here has been written for this version of the firmware.
Network Configuration
Even though in this case we won’t be using this as VoIP over the network, it still needs a network connection to operate.
In the Network Setup > Network Service set this to Bridge. This will allow a computer plugged into the yellow ethernet port to access / pass through to the blue Internet port which would be connected to your LAN.
Make a note of the SPA122’s WAN MAC Address, found in Status > System Settings, it may be useful for finding the box on your network when you make it available on your LAN in the next step.
Now to access the SPA122’s web pages from your LAN, go to Administration > Web Access Management and set Admin Access to Enable. Apply the changes and attach a cable from your LAN to the blue Internet port, you should now be able to login from any computer on your network. Your main router will have a list of attached devices, use the MAC address to help quickly find the designated IP address. The computer you were using to configure the ATA may need restarting to pick up an IP address from the LAN.
Although I have not tested this, with a handset attached to one of the phone ports dial * * * * and listen, if you can hear a slightly sinister automated voice saying “System Configuration Menu” then dial 1 1 0 # slowly, the key presses are read back to you, the device will then tell you its IP address 192.168.x.x.
SPA122 Ports
Telephone Configuration
Now we are in the Voice section. At this stage listening on a handset just produces silence, or a quiet buzzing, like from a poor power supply. For setting up the ATA will need to be restarted several times. Go to Quick Setup and set the user and dial plan for each line. The dial plan describes how the call is to be handled, numbers can be blocked, routed to different ones, or in this case be routed to another port.
Line 1:
User ID: 101
Dial Plan: (*xx|[3469]11|0|00|[2-9]xxxxxx|1xxx[2-9]xxxxxxS0|xxxxxxxxxxxx.|<018118055:101>S0<:@127.0.0.1:5061>|)
Line 2:
User ID: 100
Dial Plan: (*xx|[3469]11|0|00|[2-9]xxxxxx|1xxx[2-9]xxxxxxS0|xxxxxxxxxxxx.|<018118055:100>S0<:@127.0.0.1:5060>|)
I have used 018118055 as the number, but you can set this to anything you like. Both phones are on the same number, but they behave separately so you can ring one from the other. If the phone has a caller ID display it will show the user ID, 100 or 101.
Click submit to save the changes, once restarted and logged back in, we now need to add a bit more detail, go to Voice > Line 1, and set the following:
Proxy and Registration:
Make Call Without Reg:
yes
Ans Call Without Reg:
yes
Audio Configuration:
Preferred Codec:
G729a
Second Preferred Codec:
G711u
All lines that start with FAX:
set to no or none as appropriate
Modem Line:
yes
The FAX settings are to do with using modems in the future. All other settings can be left at their defaults. Click submit to save the settings, this takes a few seconds, and once you have logged back in go to Voice > Line 2 and set the same settings as those you just set for Line 1.
You should now be able to make a call from one phone to the other, but the ring and dial tones will sound wrong as they are for those used in the USA.
Setting the Tones
Now we need to set the dial tones and ringer for those used in the UK, in Voice > Regional you can see there are quite a few options to be set, but here I will only be setting the ones most commonly used.
Inkscape is a free vector graphics editor for all major platforms, generally it is aimed at art and design users but it does have an option for generating G-Code for use in your favourite CNC software. While Inkscape doesn’t have many of the functions of proper CAD/CAM software it is an relatively easy place to start for creating basic designs, I have been using it to make boxes out of 3.5mm plywood.
These notes are based around my cheap CNC machine sold as an CNC3018 by a variety of Chinese manufacturers on Amazon and eBay, the included controller is a Woodpecker CNC board (Ardunio clone) I have upgraded to GRBL v1.1 and I am using version 0.92.4 (April 2019) of Inkscape with the included Gcodetools.
CNC Wood Cutting
This post focuses on setting up Inkscape for the CNC machine and producing the g-code from your drawing, it is not intended to be an Inkscape tutorial.
Document Setup
With a new drawing set your Document Size, this should be the same as your CNC bed, in my case this is 300 x 180mm. From the Inkscape menu go to File > Properties and in the Page Tab set the Display Units (millimeters in my case), the Orientation to Landscape and Page Size width: 300 and height: 180. In the Grids Tab set the Grid Units to mm and the Spacing X and Spacing Y to 1.0. Back on your main page, turn the page grid on with: View > Page Grid.
Inkscape Document Properties
By default Inkscape scales the stroke/line width when you resize a shape, to prevent this click the the fourth box from the right in the top icon bar “when scaling objects, scale the stroke width by the same proportion”
Turn Line Scaling off to prevent the line width changing when resizing
You can save this as a template, such as: CNC3018.svg or as the document default with: default.svg by saving the file to your templates directory:
On Linux and OS X: ~/.config/inkscape/templates/
On Windows: C:\Users\<username>\AppData\Roaming\inkscape\templates
The lines you draw will need to be the same width as the bit you are using in the CNC machine. Draw a rectangle, Right mouse click on the rectangle and select Fill and Stroke…. In the Fill Tab click the X – no paint box and on the Stroke Style tab set the width to that of the bit you are using – 1.5mm, subsequent rectangles will be in the same style, other shapes will need to be setup this way too. The colour of your lines should be black, there is some functionality for different colours to represent different depths but I have not yet worked out how to do this.
Setting the line width
Layout Tips for G-Code Routing
Remember to check the dimensions of the cuts, with an outside cut such as the width and height of a box side you need to measure for the inside of your rectangle, for holes in your box measure to the outside edge, Inkscape sets distances to the outside edge.
For positioning holes for switches and the like, I add thin lines 0.1mm thick as guides and make use of the width/height settings as well as the Object > Align and Distribute options. A pair of digital vernier calipers are a great aid to discovering the required sizes. Remember to delete these before G-Code encoding.
Using guidelines for accurate layout
When generating the G-Code each shape will be seen as an individual object, so lets say you want to have two sides of your box cut from a single sheet of plywood, this would be two rectangles abutting each other with a side to be cut overlapping. As it takes four passes to cut each shape 1mm at a time, this means it’ll take six passes down the centre. To fix this select both rectangles and then Path > Combine followed by Path > Difference to make a single object.
Outputting to G-Code
Now that you have completed your drawing, save your work then convert your objects to paths by selecting all objects then Path > Object to Path. You may also want to place your drawing near the bottom left of the document, as this is where the CNC router starts. Now using Gcodetools there are three things you need to do to produce the G-Code file. None of the Gcodetools windows close automatically when apply is clicked, you will need to do that yourself. From the Inkscape menu:
1. Extensions > Gcodetools > Tools Libary…
Select Tools Type: cylinder and click apply In the overlarge green box that appears you will need to set the tool diameter and feed speed.
Gcodetools Tools Library
This can be a bit fiddly as the text can become detached from the box and the settings lost, what seems to work most reliably for me is to change to Text Objects (F8) click on the numbers you want to change and once done go back to Select and Transform (F1). Resize the box afterwards to check that it is still working – if the green box moves but the text does not then Ctrl-Z a few times and try again.
Gcodetools Tools Library – Green background is detached from the text – this won’t work.
setting
default
used
description
Diameter
10
1.5
tool bit diameter in mm
Feed
400
300
speed while cutting through the material in mm/second
Penetration angle
90
90
Penetration feed
100
100
Plunge speed in the material in mm/second
Depth Step
1
1
Depth of cut on each pass in mm
2. Extensions > Gcodetools > Orientation Points
This tells the g-code where to start, normally bottom-left on the CNC Set the following:
– Orientation type: 2-points mode
– Z Surface: 0mm – this is the top of your surface
– Z Depth: -3.4mm – this is the thickness of material to cut, a negative number
With the Orientation Points added.
3. Extensions > Gcodetools > Path to Gcode
This creates the G-code file, in the Preferences Tab set the following:
– File: output filename
– Directory: output directory
– Z safe height: 5mm – height above the work surface when moving between cuts
The filename once set doesn’t change, an incremental number is appended to the output filename. Click the Path to Gcode Tab before clicking apply (this appears to be a bug).
Your image will be updated to show the g-code routing, give this a visual check to ensure that all objects have been coded and that it looks right, the path to be taken should be in colour and contain arrows showing the direction of the router.
If there are too many arrows or if a line has arrows pointing in different directions then there may be an object underneath, check on your original artwork, in the image with the three circles below you see that A has not been converted to a path with Path > Object to Path, B has a duplicate object underneath and C is correct.
Gcode check; A and B have problems, C is correct.
The generated G-Code does not appear to include the Spindle Motor Start command – So remember to start the spindle manually in your CNC software before running the G-Code – its interesting how easily these bits break with a sideways load. Remember if you are cutting trough rather than engraving, don’t forget to put a layer to sacrifice between whatever you are making and the CNC’s bed, I use 5mm MDF/Fibreboard.
In this video I am adapting a sewing machine pedal to provide variable speed to my small Dremel drill. It’s not really suitable as the pedal is only rated to handle 80 Watts (0.42 Amps at 240 Volts) while the Dremel can take up to 125 Watts (0.52 Amps) of power, it should be alright for light work.
To control the power the footpedal has two stacks made of loose carbon disks, initially when the pedal is pressed power is passed through these and as more pressure is applied these compress to lower the resistance and allow more power through. When fully on, a metal disc engages across two contacts to allow all the current to pass. I think I would like to have a pedal that could handle more current, possibly something based around how a modern dimmer switch works.
Back in April 2016 I posted details on how a Vacuum Fluorescent Display (VFD) works and a method of driving it from an Arduino type microcontroller using transistors, while this worked well it made for a rather bulky clock. I have now rebuilt the display using proper VFD driver chips, added a rotary switch with LED’s, NeoPixel capability and used a WeMos D1 Mini microcontroller to give me internet access over WiFi so the time and date can be set using the Network Time Protocol (NTP). VFD Clock
This rebuild is much more practical than previously, it is now about 3cm deep and comprises of two boards back to back with pin header plugs/sockets as the interconnects. I have been running the clock for over a year without any problems, apart from having to switch the thing off and back on when Daylight Savings Time changes in the spring and autumn, but that’s a software (lazy programmer) problem.
Power Supply
Three different voltages are needed to operate this clock, 16 Volts for the VFD display anodes, 5 Volts for the microcontroller and NeoPixels and 3.3 Volts for the VFD cathode and other hardware.
Power layout for the VFD clock
From the 12 volt source, I split the power to a XL6009 boost module to supply 16V to the driver IC’s, the 5V power module can supply up to 5A which is enough for around 2 meters of NeoPixels. The 3.3V supply is created using a BA033T fixed voltage regulator running from the 5V module, I have used this to power the VFD cathode, the rotary encoder and VFD driver IC’s as this is the microcontrollers operating voltage. Back of the VFD Clock
Driving the Display
To drive the anodes on the VFD display I used three MAX6920 Tube Drivers, these have a four wire serial interface and can switch up to 76V on the display.
MAX6920 VFD Driver
The physical connections from the driver IC’s to the VFD anodes (grids and elements, see the previous article for definition) are those that are most convenient for the PCB layout without having to use links or through-hole connections as the order of the pins for outputting the display can be mapped later in software.
MAX6920 Anode Connections on the PCB
In this case, the first anode pin on the display is on the right, but the serial data starts with the first MAX6920 chip on the left. I will explain in more detail in the software section below.
The Cathode is run from the 3.3 Volt supply, it has a 3.3V Zenner diode across it to protect against meltdown in case of over-voltage, the cathode is made from of strands of thin tungsten wires and shows as a short when testing in beep mode on the multimeter. Zenner Diode for the VFD Cathode
Rotary Switch
I have used the SparkFun RGB Illuminated Rotary Encoder, as well as the encoding it also includes three LED’s and a push button switch. As the WeMos only has limited number of pins available, I used an MCP23008 I2C I/O Expander. I have covered these encoders in a previous post and have used a similar method here.
Rotary Encoder on the I2C Bus
In this project it turned out I don’t have much use for the rotary switch, the same result can be achieved with a push button and two LED’s, it goes red when setting the time over WiFi, goes green when the time has finished setting but is off when running normally, the push button displays the date when pushed. I expect the encoder could be used for setting an alarm should I ever have need to add one.
Software
The complete source code I am currently running in the clock can be found on my github repository, it has been written for the Arduino platform and can be considered unfinished and a bit of a mess. In almost all cases this clock will be a custom build with all the scavenged VFD displays being different I’ll be concentrating on how the display is being driven. Note that the software uses Latch and the MAX6920 driver chip uses Load.
To start, here are the physical connections for my VFD display, the display connections are shown looking from the back with pin one on the right, on the anode there are eleven grids and twenty-one elements, each grid illuminates a block of chosen elements. There are three MAX6920 driver chips, the first is on the left data is passed along the serial data line DIN/DOUT to the right: Connecting the MAX6920 drivers to the display
While I’m not going to worry too much about how the data is sent to the display as this is being handled by the ShiftOutX library it may be useful to have an understanding of the byte order sent to the driver chips.
Breaking out the logic analyser we can see what is going on, in this first image below we can see that between the two markers one and two there are eleven data peaks to match the number of grids on the display the data is processed as a padded eleven character string: ‘ 212848 ‘ the first four contain nothing but the bit selecting grid to be used the next six are busy as they contain the time, and the last is blank. There also appear to be two blank clock cycles after these, this may be a programming error on my part. Data being sent to the display
the string is iterated so that each grid gets its own character with a very short delay between each this causes the persistence of vision effect and the time appears on the display.
In the next screen capture I have zoomed into more detail, it is showing the fifth grid and is displaying the number two. You can see that there are thirty-two clock cycles sent to the drivers while LOAD is high, this causes the driver chips to direct the data to the outputs. I am not entirely sure why the clock is being run while LOAD is low, I think it may be clearing the buffer before sending the required information. Data being sent to a grid
You can see that 32 bits are sent to the display, but there are 36 pins available on the three MAX6920 drivers, you can also see that the outputs are arranged out of order. How do the drivers know which lines to switch for the display?
First off, an explanation of how the data is constructed then sent to the display. For this example I am sending the number five to the third grid, the data is constructed through the manipulation of a character array in three stages:
1.
blank char array:
00000000000000000000000000000000
2.
set the third grid:
00000000000000000000000000000100
3.
set the number:
00111000011000011100000000000100
Because of the way the bits are ordered when sent to the drivers I have a lookup array VFDlookup to make life easier, in this case grid 3 can be found at position 29 in the VFDdata character array. I start with a blank character array of 32 bits VFDblank and copy this to VFDdata, I then use VFDlookup to find the position of the bit to set: VFDlookup[3] = 29. For the elements the encoding for each character is set in VFDdigits the code for number 5 is 1110000110000111 the code was worked out by experimentation, seeing which element lit up after I had completed the hardware, I have ignored the extra symbols used for the DVD player so I only need to set pins 15-30. Once complete the character array is converted to a unsigned long integer and sent LSBFIRST – Least Significant Bit First via ShiftOut_32.
While that explains the elements encoding to display the correct digit, the grid selection however is a different kettle of fish. I built this clock over a year ago and have forgotten how it works. Grids 1 and 2 are connected to the output pins 1 and 0 on the third driver, pins 2-5 are then skipped, and the rest are connected to the grids, with three more being taken from chip 2. I can’t work out how it knows to skip those pins, or that grid 2 is connected to pin 1. But it is an awesome clock though.
My fridge door tends to rebound when closed staying open a smidgen and letting all the cold out. Rather than just checking that the door is properly shut, I thought it about time to have a microcontroller make a noise when the door has been left open too long.
This circuit uses an Arduino compatible Teensy LC for all the work, it has a phototransistor to sense the state of the fridge door light, a couple of LED’s one to indicate the power and another that comes on when the door is open. There is also Piezo buzzer to make an annoying noise after forty five seconds of door open time. The unit runs of a 3.7v rechargeable Lithium-ion battery and I have added a recharging circuit that takes power via the Teensy’s 5v USB port.
Circuitry
Note: These diagrams show 3.7v as the supply voltage. The Teensy LC can only tolerate a maximum 3.3V on the data pins, so these circuits are driven from the 3V output on the Teensy. They will all work without modification on the 5v Arduino Uno.
I have used a phototransistor to detect the fridge door light, there are two variants of this circuit light activated or dark activated, the 100k resistor can be replaced with a 100k variable if you need to adjust the sensitivity, the 330k resistor provides a weak pull-down on the output. The phototransistor is being used in switch mode to provide a logical output (rather than active mode which provides an output relative to the amount of light), so the output is connected to a digital input on the Arduino. The BC547 transistor is half of the darlington pair to provide extra gain on the output.
Dark Activated SwitchLight Activated Switch
I chose the light activated switch, either will do but will provide different logical outputs to your controller. The circuit is enclosed in a small box inside the fridge and connected by ribbon cable to the controller, the ribbon cable is flat and does not upset the magnetic ‘seal’ on the fridge door.
Component Connections
To make some noise I used a piezo buzzer from an old computer, this is driven through a transistor as the Teensy does not provide enough current to drive it directly.
Piezo buzzer
There is also a push button to provide a reset function if the buzzer is sounding while the door is open.
Push Button
I have also added two LED’s, one to show power and anther that illuminates when the door is opened.
Power and door LED’s
The final circuit if for recharging the battery, it connects to the 5V connection on the Teensy LC so charges the battery when the USB connection is in use. This has been copied from the MCP3831T datasheet.
Battery Charger
Software
This uses an interrupt to listen for the light sensor, when the state changes, the door open pin is read to determine if the door is open or not. If it is then a timer is started, this gives you forty five seconds to complete your task before the alarm sounds. With the door closed the timer is stopped and set back to zero. If the sounder goes off while you are rummaging in the fridge the reset button can be pressed, this restarts the timer from zero again.
Fridge Door Open
Arduino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#define TEST_LED 13
#define FRIDGE_DOOR 6
#define DOOR_LED 8
#define POWER_LED 7
#define RESET_BTN 9
#define BUZZER 10
volatilebooleandoorOpen=true;// when the light is on
volatilebooleandoorTrigger=false;
volatileunsignedlonglastFridgeMillis=0;
volatileunsignedlongfridgeTimeoutMillis=10;
booleanSerialDebug=false;
unsignedlongdoorOpenDelay=45000;// 45 second timeout before buzzer sounds
This all started with wanting to modify a cheap camping light by replacing the LED’s with some colourful NeoPixels. I made a Printed Circuit Board to match the existing PCB disc that held the LED’s, as well as a board for an ATtiny85 microcontroller which incorporated a microphone and vibrating motor of the type used in a old mobile phone. The battery and charging circuit came from a cheap (Poundland) USB powerbank but it turned out that the battery from the powerbank didn’t fit in the camping light how I liked (in a measure twice, cut once sort of thing). Instead I made this:
The corner of one of my SD cards broke off and would no longer latch properly in the cameras slot, it was time to either throw it away or repair. I opted for repair.
For the repair I used some Poundland two part epoxy resin as this can be used to fill in the missing section and when fully cured, after 16 hours, is just as strong as the plastic its replacing.
I started with a sheet of glass from a picture frame to give me a flat surface, upon which I stuck a short strip of electricians tape as the epoxy resin wont stick to this, next I applied a small blob of resin to the tape over which I placed the SD card to cover the entire broken corner that you see in the photo then squeezing down to push out the excess. I then left it for about ten minutes to let the glue set a little when I could push the glue up and fill in the corner.
I then left it for about an hour to go solid but still pliable, I then peeled the tape off from the glass and glue. The next stage was to trim down the excess with a scalpel, this tided up the outer edges but still left a ridge by one of the contacts, in the morning I removed this by carefully filing it away. I finished by cleaning with isopropyl alcohol.
I wrote this back in May 2017 but it was never finished, I got distracted by other things and I needed the wireless controller for photography. I wrote all this and it would be a shame to delete it, so I am posting it now on the chance there may be of something of interest within.
I use this Yongnuo Wireless Controller in photography to control a number of flash units away from the camera body. It comes in two parts, a transmitter that connects to the hotshoe on the camera and receivers with a hotshoe that connect to the flash, a single transmitter can control any number of flash receivers within the claimed 300 meter range. The transmitter with a couple of receivers can be gotten of eBay for around £35.
Investigate how the transmitter works – reverse engineer as much as I can
See if I can control the transmitter directly with an Arduino
See if other devices using the same radio chip can also be controlled
Not destroy the transmitter while examining it
Opening it up
[images of the transmitter insides]
On the board inside you will find:
A power on/off switch
Bi-colour Red/Green LED
A dual-press button with two switches for operating the flash manually
A four way code selector (4 way DIL switch)
An anonymous (no markings) microcontroller – µC
A7105 2.4GHz FSK/GFSK ISM band wireless transceiver
On the underside, my board is marked with the following version and date:
Version: 1.21
Date: 14/04/23 – 23 April 2014
Looking at the datasheet for the A7105 it can work as both a transmitter and receiver and uses an SPI interface for user control, it appears to be popular with the radio controlled RC aeronautical drone community. The receiver looks to be very similar by way of components, using the same radio chip and anonymous microcontroller. I have not examined it in any detail and take care if disassembling as there are three hotshoe connections that need to be desoldered.
RF-602RX receiver
Flash Connection
On the Canon camera the hotshoe has six connections but we only need to examine three of these. Looking down on the camera with the lens facing away from you, the main plate where the flash slides in is ground, the large central dot is the flash trigger just below this on the left is the camera ready connection. I assume the rest are for the E-TTL functions and I have not looked at these.
Canon Hotshoe Connections
Checking the hotshoe with a multimeter, the flash trigger appears to have a high resistance that decreases when the flash is fired, I suppose this is a legacy of when cameras were more mechanical. The Camera Ready connection goes High – around 5 Volts, to tell the flash to wake up, that you have pressed the shutter halfway, the lens has focused and you are about to take a photo.
To find the duration of the flash signal on the cameras hotshoe I connected an almost flat AA battery between ground and flash to give me 1.2 volts to measure against on the oscilloscope (checking a canon flash itself, the voltage across the flash pin and ground is 4.47 volts). I found that the flash signal is sent by the camera for 352ms, which is quite long considering that a typical shutter speed of 1/125 second for flash photography works out at 8ms, although the amount of time a flash fires for is set on the flash and not by this signal.
Capturing the flash event
Microcontroller Connections
I spent a while tracing out most of the transmitter circuit, I have ignored most of the supporting radio circuitry and the crystal timer as I am wanting to investigate the data side. The parts are also rather small and troublesome to investigate with standard multimeter probes.
RF600TX – Partial Schematic
The microcontroller looks to use internal pullup resistors for the input switches, the camera ready signal from the hotshoe switches a transistor to pull pin 16 low on the controller.
Looking at the circuit diagram we see an output to the antenna from pin 8 of the micro controller. This outputs two different square waves when the shutter button is pressed, one for camera ready and another for flash. I think these are being modulated on the transmitter output to produce a radio signal and simplify the transmitter design. Looking at the output from pin eight on the oscilloscope, the two states can be seen quite clearly:
Camera Ready signalFlash signal
These square wave outputs are always the same, I thought it may change when a different code was chosen through the DIL switches. The transmitter unit does not receive any radio data, and no acknowledgement is made by the flash units.
Using a Logic Analyser
Time to break out the Logic Analyser, this is a cunning device that allows you to see the data being exchanged between the microcontroller and transceiver, I don’t want to get too detailed but think this may help for the following sections.
The data system being used by the A7105 is SPI. The Serial Peripheral Interface bus uses four wires: Chip Select SCS, multiple chips can be on the same SPI bus, but they all have different SCS connections, the master controller chip uses SCS to tell the slave chip it wants to use for data exchange. Serial Clock SCK: This is used to provide time synchronisation for the data exchange with a fixed duration for the highs and lows. Data SDIO: This is the data being sent by the microcontroller and GIO1 is data from the transceiver sent in reply, normally for SPI this is 8 bits, to make a byte.
The naming conventions used here are from the A7105 datasheet, The SPI bus has standard names for data lines; SDIO is MOSI – Master Out/Slave In, GIO1 would be MISO – Master In/Slave Out and SCS is SS – Slave Select. In our case the microcontroller would be the master and the transceiver the slave.
SPI Single slave
The Logic Analyser displays data in a form that allows you to see the logic, here we can see two bytes of data:
Example of SPI data
The microcontroller – µC sends data on the SDIO line and listens for replies on GIO1. When the µC sets Chip Select SCS low this tells the transceiver that the µC wants to talk to it. The µC sends a command byte followed by one or more bytes of data – a packet. During the SCS event, data is only transferred while the clock SCK is running.
SPI data, binary data from the highs and lows
We can see that the logic on the SDIO is read every-time the clock goes low, falling edge, a clock tick on the SCK line represents a bit of data, eight ticks make a byte. We now have our binary data: 00100101 for convenience this is converted into hexadecimal 0x25.
When examining an SPI bus check any available datasheets to see if the clock is set to tick on a falling or rising edge, the bit order is Most Significant Bit – MSB or Least Significant Bit – LSB, and the data length (normally eight).
Looking at the A7105 Transceiver
A7105 Block Diagram (a clearer version can be seen in the datasheet)
From the A7105 datasheet the SPI bus is set for the following:
To activate SPI, the SCS pin must be set low
data length: 8 bits
bit order: Most Significant Bit First (MSB)
I have made the following connections to the transmitter. Soldering test leads to the microcontroller (µC) is the most convenient place to do this.
Connections to the Logic Analyser
This table shows the Input/Output pins on the transceiver and microcontroller, as well as the colour of wire used for the logic analyser.
A7105
Description
In/Out
µC
Wire Colour
11
SCS
3 Wire Chip Select
I
9
yellow
12
SCK
3 Wire Clock
I
10
orange
14
SDIO
Read / Write
I/O
12
brown
16
GIO1
4 Wire SPI Data Output
I/O
11
red
17
GIO2
4 Wire SPI Data Output
I/O
13
white
GND
Ground
black
Trigger Out
O
8
grey
How the A7105 organises data
The transceiver has two data modes, Strobe and Control. There are eight strobe commands to control the various modes the chip supports, these are four bits in length and always begin with a 1, where the transceiver is being operated in 8 bit mode the final four bits are ignored. The Control registers are eight bits in length and are used to configure and read settings from the transceiver, they are eight bits in length, the first bit is always 0 and the second is either 1 for write or 0 for read. The table below shows examples of a write, a read (or more accurately a request, the transceiver replies on GIO1) and a strobe command sent by the µC.
Address Byte
Data
Bit:
7
6
5
4
3
2
1
0
7
6
5
4
3
2
1
0
Control:
CMD
R/W
Address
Data
Write Example: 0x2 0x1
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
Read Example: 0x42 0xff
0
1
0
0
0
0
1
0
1
1
1
1
1
1
1
1
Strobe:
CMD
Strobe ID
not used
not used
Example: 0xa0
1
0
1
0
0
0
0
0
Examining the A7105 data
Data is exchanged on the SPI during two events, after the transmitter has been switched on, and when you are pressing the camera shutter or the button on the unit.
Power On
Extract of the SPI power on data showing SCS event 48, see the spreadsheet for more details
When you first switch on the unit, the microcontroller initialises the transceiver with a few hundred bytes of data, I have created this spreadsheet from the SPI data, hex data across is the most useful sheet to view:
In summary the initialisation sequence consists of the following
The microcontroller sets the majority of control registers to default
Internal calibration is started and the microcontroller keeps checking until this is done
Final cleaning up
Place the A7105 into standby mode
Shutter Press
On the SPI the shutter press action has two distinct stages, the preamble and the transmission. The preamble takes the camera out of standby mode and sets the channel it is going to be transmitting on. The transmission broadcasts the camera ready and flash states.
The Preamble
At the beginning of the datacaptue I see a preamble packet sent over the SPI:
Logic Analyser Data – first five bytes of the Preamble Packet
This preamble looks to only appear when the flash is first operated after the transmitter unit has been switched on, subsequent use goes straight to transmit. The fifth byte changes depending on the DIL switch setting on the underside of the unit, as you can see in the four examples given in the table below.
bytes
DIL switch
strobe
control
data
strobe
0000
0xB0
0xB0
0x05
0xB5
0xF0
0xD0
1000
0xB0
0xB0
0x05
0xB5
0xE1
0xD0
0100
0xB0
0xB0
0x05
0xB5
0xD2
0xD0
1111
0xB0
0xB0
0x05
0xB5
0x0F
0xD0
Taking the first example, we can break this down to see what each byte is doing
SCS
Packet
IN/OUT
Command
Payload
binary
0
0xb0
STROBE
PLL Mode
0b10110000
1
0xb0
STROBE
PLL Mode
0b10110000
2
0x5
0xb5
0xf0
IN
FIFO Data
TX data
0b00000101
0b10110101
0b11110000
817µs gap
3
0xd0
STROBE
TX Mode
transmission begins
0b11010000
It is difficult to work out what is going on here, according to the datasheet you send a packet of data 0xb5 0xf0 to be transmitted to FIFO Data0x5 and follow that with the strobe command TX mode0xd0, but what is transmitted bears no relation to the FIFO packet.
We need to look further back in the initialisation sequence and the datasheet, the A7105 has three modes of transmission; easy, segment and extension. We need to undertake a little bit of detective work to find which this is. Chapter 16.4 of the datasheet shows us the two registers used in the initialisation sequence we need to examine:
Bit:
7
6
5
4
3
2
1
0
FIFO I
0x3
FEP7
FEP6
FEP5
FEP4
FEP3
FEP2
FEP1
FEP0
Setting value:
0x1
0
0
0
0
0
0
0
1
FIFO II
0x4
FPM1
FPM0
PSA5
PSA4
PSA3
PSA2
PSA1
PSA0
Setting value:
0x0
0
0
0
0
0
0
0
0
The datasheet does not say directly so we need to go through each modes description to see which is the best fit. Segment FIFO looks good: “In Segment FIFO, TX FIFO length is equal to (FEP [7:0] – PSA [5:0] + 1). FPM [1:0] should be zero”. So our settings: (FEP:0b1 – PSA:0b0) + 1 = 2. The number of bytes sent our FIFO Data packet is also 2.
Further reading of the description “This function is very useful for button applications. In such case, each button is used to transmit fixed code (data) every time. During initialisation, each fixed code is written into corresponding segment FIFO once and for all. Then, if button is triggered, MCU just assigns corresponding segment FIFO (PSA [5:0] and FEP [7:0]) and issues TX strobe command.”
The Transmission
Taking an initial look at the data gathered during a shutter press on the Trigger Out (pin 8 of the microcontroller) we can clearly see the transition from Camera Ready and Flash as we saw on the oscilloscope earlier.
Logic Analyser Data
GIO2 shows a mirror of the Trigger Out, but zooming in to the data and I see that it follows the Trigger signal. Looking in the initialisation spreadsheet at SCS event we see that the command 0xc 0x1 was sent for setting the function of the GIO2 pin. Looking at the datasheet this appears to be set as an ‘I am transmitting’ signal, WTR – Wait until TX or RX has finished. If I force GIO2 low by sorting it to ground then the flash does not fire when I press the shutter
Logic Analyser Data
In my data capture the Camera Ready signal was transmitted six times, and the Flash signal thirteen times, I am sure this is dependant on the length of time I had the shutter button pressed on the camera.
Apologies for the inconclusive ending, I ran out of time to pursue this further