20261018
Changed Timing.h so it will not wait for its 10 min schedule, if the board starts at any minute inside the scheduled time it will starta at next 2 min window to tx a standard wspr packet and then resume the order of schedule you have set.
20261017
Major overhaul of the code, biggest enhancements is the mergin of the 180° tx code with the normal tx code with a setting to run the board in standard - normal (true/false flag) dipole mode or in 180° mode with the dipole halfs fed 180° antiphase, quadruple the power output but only doubling the power consumption of the si5351 - in theory. Power demands increase from 25mA in dipole to 30mA 180 degree mode, also lots of old unused code mainly the jt9 codesnips that was left in there removed, all user configureble settings moved to one place in the beginning of the .ino file - new and old pcb:s 100% compatible but old pcb:s does not have clk1 routed that is needed for 180° tx so only dipole mode works on them. (si5351 use about 17mA in stb and 27mA in tx using clk0 + 5mA for clk1.)
Bugfix: if slot on minute 8 was used in previous fw it jumped a 10min seq before it started tx again - now been fixed
Fixed a bug in telemetry/gps data and moved all configurable settings into the .ino file, like channel and tcxo freq
A 180° tx with a 4x power output avalible here: https://github.com/micked99/ICT-wspr-180-4x-the-power-output
BOM and Pick and place files added if you want to for example JLCPCB to make and assamble the complete board
BOM_ict_v361-xs.csv & CPL_pick place_ict_v361-xs.xlsx
Screenshots of the settings of order of pcb assembly, see folder "JLCPcb order"
Get your board online onto Sondehub/aprs.fi section added
Consider a donation to this projects software developer at: https://yo3ict.uus.ro/index.html press the "Show Sponsors" button
If you do find the following compilation of information of use - Donation
This FW is mostly the work of Eduard YO3ICT, you can read about here: https://yo3ict.uus.ro/tracker.html
What I have done is to simplify it even more with a few less components and a slightly easier to solder pcb.
What Eduard did was reverse enginer the QRP-Labs telemetry protocol which use wspr to get data through, and open sourced it, details of the protocol is described here: https://qrp-labs.com/flights/s4#protocol most balloons use this encoding today, with a few exceptions, like Zachtek
Another good site for beginers is to read up and join the io board at: https://groups.io/g/picoballoon
The Traquito page will host channel reservation and upload to varous tracking sites like https://aprs.fi/ and https://amateur.sondehub.org/ and as well host its own map, more maps and info avalible here https://lu7aa.org/dx.asp and here http://qrp-labs.com/tracking.html, another good page that poped up lately is wsprtv & wsprtv channel map
The Arduino code to upload to the PCB
Copy the content in this folder into libraries folder of Arduino C:\Program Files (x86)\Arduino\libraries
Cam files for pcb ordering as well as the Eagle schematic and board files, viewer for both files here: https://www.altium365.com/viewer/
Replace the Boards.txt in arduino to controll the speed of the 328, its located in: C:\Program Files (x86)\Arduino\hardware\arduino\avr
This setup is aimed at three main things: light weight, low power demands and as few components as possible - easy to build
The board can be built to weigh below 1 gram fully assembled (pic below) with solar cells & antenna connected total weight 4-5 gram
To make the board consume as little power as possible its setup to switch between tx and gps so only one of the two is ON at any time, so it will startup and get valid gps lock with tx side of the board switched off, the tx ic - si5351 consumes 17-27mA (depending on model) in stb curent even when not in use so only the gps is on and draws about 25mA using the ATGM336 (N31), when the board have got a valid lock the gps will turn off and the wspr tx starts, it will be about 30mA, on top of this the 328 running at 2Mhz and the Tcxo combined will take another 3mA
The board will work on any band between 14Mhhz and 28Mhz
CW init - At power on, when sun hits the solar panels it start to tx cw, then you know you are good for launch
No tx over selected grids - Move tx to ism (13.555) freq over selected grids
Powerswitching between gps and tx - Will put less stress on the cells and get earlie in the morning startups
Course altitude in main wspr - Will insert a rough altitude into the standard wspr db field, see TelemFunctions.h
Good WDT function of 328 - Will never fail to wake up even with unstable solar cells powering the board
Will work at low clocks, tested down to 1Mhz on the 328 - Deafult is 2Mhz
Powersave of gps by set it to single navigational system - See Gps section
The ATGM336-N31 support both GPS and Beidou system, by switching off Beidou and run the ATGM in GPS only mode we save about 4mA, see .ino file for the command, gps only is activated by default.
This gps does not have any altitude limit like many other modules, its been tested to 150.000m with a hack-rf and GPSSim and still worked fine
All components but the si5351 is bought on Aliexpress, you can source the SI535/MS5351 on Ali but they can have an higher power consumption then the original, from my experience the Ali ones draw 27mA instead of 17mA in stb current of the genuine ones
Cpu ATmega328P (328PB also works but need installing MiniCore in Arduino IDE)
Gps ATGM336 (N31) others will work
TX Si5351
Tcxo 25/26/27 Mhz size 3225 3.2x2.5mm
Xo 4Mhz size 4520 4.5mm×2mm
2x 10K resistor size 0603, value non critical, 1K-10K works
2x 100nF Capacitor size 0603, value non critical 10-470nF works, it will work fine without any soldered on but I recommend at least one
2.54mm x2 Pin Header - Remove before flight by cutting it of with a scissor
For gps antenna use a 46mm wire which represents a 1/4 antenna at 1575Mhz
For tx antenna I use 0,15mm which is a good combination of strength and weigh but any wire in the 0,1 - 0,2mm will work fine, try enameled copper wire that is heatstrippable
I use a small hook 2cm long made of 0,6mm wire bottom, and 0,8mm at the top to solder on the antenna wire, solder and twist a couple of turns arround the hook
Here is good picture where you can see the Red and Yellow gps antennas
Tx Antenna length calculated as normal, 300/freq x 0.95 /4
Upper antenna leg should be supported by a fishing line taped between the balloon and pcb
6 psc of solar cells connected in series will work fine, or 4 psc of a bit larger cells and a voltage doubler with 3,3V ldo like REG710 will do the work, ready made pcb are avalible on Aliexpress, search for "Low Noise Regulated Charge Pump" see below pic
Do not try use converters with an inductor, they will not work, only converters using a capacitor are likeley to succeed.
As can be seeen in the below picture the solar cells is intended to be soldered to the board with a center copper rod of 0,8mm, notice,
there are two pairs of vias, one is GND and one pair is not connected to anything which is where you solder the center support for the cells - see below pic
OBS! The programming pinhead should be cutoff before flight and preferably before you solder the cells onto the pcb
Solderpoints for the solar cells
With 6 x 38x19 cells ounded flat you can see a startup of the board at about 13° solar angle
How I solder the cells together, I use a 0,6mm wire I extract from a multi stranded electrical cable, and then a very thin wire from an even smaller multi stranded cable to solder the cells to the pcb, pics:
To test the solar + board indoor before a flight you can use a Halogen flood light like below pic, I use a 400W, 8545 lumen lamp.
-OBS- Led lamps wont work.
To compile and upload the sketch I use Arduino version 1.8.13 which you find here, others will work but not tested,
https://www.arduino.cc/en/software/OldSoftwareReleases/
Resently tested last version as of now 2.3.10 which also worked fine.
Sets the expected external or internal xo used and also set the brownout to 1,8V
The 328 have an internal xo at 8Mhz, you can set it to be divided down by 8 (fuse) and then the board runs at 1Mhz the internal xo at 8Mhz is not very stable in cold and it will not work at flying altitude, but I have tried a few flights on the internal xo divided down to 1Mhz and it have worked fine, anyway, both speeeds works fine for testing a board on the bench, but I do recomend that you use the suggested 4Mhz xo as in the schematic.
FD D9 FE 1,8V / External 2/4/8Mhz xo, Brownout to 1,8V - This is the fuses you should use if you build this board
62 D9 FE 1.8V / internal 8Mhz osc /div8 = 1Mhz
E2 D9 FE 1.8V / internal 8Mhz osc
To set fuses use Avrdudess https://github.com/ZakKemble/AVRDUDESS
Fusecalc page https://www.engbedded.com/fusecalc/
I would recommend to buy a couple of arduino nano boards to practice on before flashing fuses onto a built board, as this is the main culprit of non responsive 328 - wrongly set or corrupted fuses
The pcb is fited with a 6 pin ISP connector
The Arduino uploads the fw with an USBasp programmer, get a 3,3v version with a 10 to 6 pin header adapter on the end of the ribbon cable
To upload a .hex file like the one supplied in oscillator-main folder I recommend using AVRDUDESS - A GUI for AVRDUDE
https://blog.zakkemble.net/avrdudess-a-gui-for-avrdude/
https://github.com/avrdudes/avrdude/
Use libsusbK in Zadig to install driver for the Usbasp: https://zadig.akeo.ie/
In Arduino IDE select Usbasp as programmer:
I have always used Jlcpcb at https://jlcpcb.com/ for my balloon boards and other projects
The pcb files have been made with Eagle pcb nowadays under the name Autodesk Eagle https://www.autodesk.com/products/eagle/overview
Make the PCB as thin as possible to save weight, 0,6mm is good compromise between weight and price
In Pcb-ICT-main folder in this repo you will find needed CAM files in the zip´s, if you are a experieced with solder small parts and have a hot air solder station go with the Xtra Smal QFN version (ict_v361-xs.zip) of the board, for a more simple soldering setup use the TQFP version (ict_v361.zip)
Here is what a JLC-PCB assambled board looks like, pictures from Michael KC3GMG


The Arduino code is setup from start to use a 26Mhz Tcxo and a 4Mhz crystal, if other values used the code needs to be changed - see below
Values to edit in the ino file
const char call[] = "SA7BSS"; // WSPR Standard callsign -- SA7BSS for bench testing, SA6BSS for flight
char tlm_channel1 = '1'; // Telemetry channel: 0/1/Q
char tlm_channel2 = '1'; // Telemetry channel: 0-9
const uint32_t tcxo = 26000000UL; // TCXO/crystal frequency in Hz
const bool use180deg = false; // Hardware config: true = 180° dipole (CLK0+CLK1), false = standard/ground-wire (CLK0)
See this page for channel setup and reservation: https://traquito.github.io/channelmap/ & https://wsprtv.com/tools/channel_map.html
CW setup, the board will at first moment at power on send a morse signal with your callsign
This is a first good test the board is working, set the freq in Beep.h, it will beep without a gps soldered
Here is my SA6BSS call in the ino file
cw_s(); cw_a(); cw_6(); cw_b(); cw_s(); cw_s();
Testing and Scheduling of tx sequence
After power on it will beep a cw for 5 sec then switch over to gps that takes about 25-30sec to get a GPS fix if in clear sky or gps repeater used, GPS through a window can take 1-2 minutes.
Edit Timing.h sceduling at what minute you want to tx your normal wspr and at what minute to tx the telemetry, this can be done inside Arduino ide or with a normal texteditor, this is self explanatory
const uint8_t TX_SLOTS = SLOT(0) | SLOT(2) | SLOT(6) | SLOT(8); // minutes that transmit; any other even minute is idle (GPS only)
const uint8_t TLM_SLOT = 2; // minute that carries the telemetry message (must be one of TX_SLOTS)
const uint8_t PREP_SLOT = 6; // minute where new GPS data is read (the first TX slot after the idle one)
"PREP_SLOT = 6; "This can be a bit unlogical but its the first tx after the GPS got new data, we can see "TX_SLOTS = SLOT(0) | SLOT(2) | SLOT(6) | SLOT(8); " where 4 is the slot where the radio switch off and the gps enables, so PREP_SLOT = 6; is the first slot after gps got new data into the board
To adjust the sequence in what order the standard and telemtry is transmitted edit Timing.h, it is set to transmitt 4 times - 8 minutes and then switching off the radio and enable gps, gets new loction data, then start over.
This is the standard setup using a 4 Mhz xo, so if you build the board with the recommended components and downloaded fw this does not need to change
Sets speed of the board
clock_prescale_set(clock_div_2); or clock_prescale_set(clock_div_4);
this in conjuction with:
#define WSPR_CTC 1334
and select rAVA 2Mhz from boards in Arduino boards
Alternative clocksettings:
WSPR CTC - 2668 @ 4Mhz //1334 @ 2Mhz //667 @ 1Mhz
And to select the appropriate board setting under Boards in Arduino,
lets say we want to set the board to 1Mhz using a 4Mhz xo we need to set the prescaler to
clock_prescale_set(clock_div_4);
and set
WSPR CTC 667
and then select gAVA 1Mhz under boards, see section Programming
then, for example if you wan to run it a 4Mhz set:
WSPR CTC - 2668
mark out both of the //clock_prescale_set
and use hAVA 4Mhz board setting
to set cw tx frequncy adjust it in Beep.h, this will tx a short cw init as soon as you connect power
freq = 14096980UL;
// freq = 18105900UL;
// freq = 28125870UL;
You want the board to be as leveled as possible so the solarcells always points up and not to the sides,
to do this use the top hook, puti it on a short loop of fishing line and bend the copper rod untill it levels up, see below:
There is a couple of ways to get your board onto Sondehub
The way Im doing it is to use a wspr-to-sondehub python script described here: https://github.com/micked99/wspr-to-sondehub-script
What I do is to use this script with a filtering function so your upload data dont get mixed with other flights - you should check the channel is free here before relesing a balloon: WSPR-TV but as the 600 channels per band is relaying on filtering on frequency and this script cant handle that, this is a simple workarround.
So the idea I got and that DG4NOB implemented in the python upload code was that we can use the voltage reading of the battery as a filtering function, as we use solar cells, voltage is mostly of no interest, reading the Encoding Description we see "Battery voltage is coded by a number in the range 0..39, which represents battery voltage in the range 3.00 to 4.95V with a resolution of 0.05V" this means we have 40 unique "channels" within this, so what we can do is to set a static value in the ict fw and uplod this to the board,
look at lines 126 - 132 in TelemFunctions.h and you see this:
sensorVolt = sensorVolt / 5; // mark out for fixed voltage
volt = sensorVolt * 1.1f; // mark out for fixed voltage
volt = volt / 1023.0f; // mark out for fixed voltage
volt = volt * 4.18f; // mark out for fixed voltage
// volt = 3.94; // --Remove if sensor voltage is used--
if (volt < 3.0) volt = 3.0; // mark out for fixed voltage
if (volt > 4.95) volt = 4.95; // mark out for fixed voltage
The normal setup is as above where the adc reads the voltage on sensorpin, it should be a voltage divider there but I have routed the pin directly to vcc so if you dont make any edits to the code it will constantly read 4.56V, so what we can do is to change the code, say we want to filter the voltage to 3,94V we edit the code to:
// sensorVolt = sensorVolt / 5; // mark out for fixed voltage
// volt = sensorVolt * 1.1f; // mark out for fixed voltage
// volt = volt / 1023.0f; // mark out for fixed voltage
// volt = volt * 4.18f; // mark out for fixed voltage
volt = 3.94; // --Remove if sensor voltage is used--
// if (volt < 3.0) volt = 3.0; // mark out for fixed voltage
// if (volt > 4.95) volt = 4.95; // mark out for fixed voltage
After we done this and upload the code to the pcb we should have a fixed voltage reading constantly sending 3,94V which we can put in the balloon.ini file in the wspr upload script
If you have launched the board with no editing to the ict code you can set 4,56V as a filter, this making it work on boards allready in flight.
You need to double check the voltage readign your board actually tx as there will be a 0,01V variation on the actual value that comes out of the decoder, even if you set 3,94V it might be 3,95 that comes out, you can test it in this xls
https://qrp-labs.com/images/ultimate3builder/ve3kcl/s4/308d.xls
originating from https://qrp-labs.com/flights/s4#protocol
Other ways to get you board online is to use https://lu7aa.org.ar/wsprset.asp
There is also an uploader by Bill WB8ELK - maker of Skytracker that you can download from Here
You need to be a member of this io board to access it, it will upload to aprs.fi and Sondehub will then automaticly pipe it onto its site,
pros of this program is easy to setup and it can filter on Frequency as the 600 channel mapping require.












