Exploration of Morse with FS1000A 433mhz module & ESP8266 - Page 1
Forum section: electronics / general

author: TreefrogX
author_rank: Newbie
timestamp: July 31, 2018, 07:57:46 pm
content: Hi All,Here's a one-night-stand project I did. I thought I'd share it as it was quite interesting and perhaps it'll help somebody explore it further.Whilst somewhat inebriated last night I decided to start a high altitude balloon project, or at least to investigate a telemetry system. I grabbed a FS1000A 433mhz Transmitter (the CHEAP green modules on ebay that come as a TX/RX pair). The TX is ok but the RX circuit is useless, so I opted from the start to use my SDR dongle and to do the decoding directly on my PC. Besides, I recently found a 440mhz antenna in a bin and took pity on it and thought it deserved a fresh start in life... Humans can be so cruel to hardware.The FS1000A TX only supports ASK, which is easily enough handled by the RadioHead ASK library (http://www.airspayce.com/mikem/arduino/RadioHead/) which I had running on Wemos D1 Mini (ESP8266).I couldn't find any Windows software to decode ASK, though eventually I found RTL_433 (https://github.com/merbanan/rtl_433) which sort of works, but not as I needed. It dumps debug info to screen but is awkward as a datasource because of all the parsing that would have been required e.g. It printed the payload message as ASCII numbers, which made it a pain to debug/enjoy as I couldn't read the messages via the Mk1 eyeballs. I started trying to hack the RTL_433 code to instead output a string to my taste, and it turned out to be dead easy, but I didn't have a c++ compiler, so whilst waiting for the LONG download of C++ for Visual Studio, I got sidetracked...Is it possible to send morse using this thing?The quick answer is yes, sort of.At first I started by pulsing dit's and dah's by making the tx pin high or low for varying times using delay().Dit: HIGH 100ms - LOW 100msDah: HIGH 300ms - LOW 100msListening to the audio received via a $20 USB stick and SDR# (https://airspy.com/) I could clearly make out my test message; as a human. Transmitting pulses of on and off meant I could interpret the carrier pulses as morse, but none of the CW (Morse code) decoder programs I could get working on my PC seemed to be able to parse it. What I was effectively transmitting was morse over Amplitude Shift Keying, so I made a guess that the decoder apps were looking for an audible carrier tone, as you'd hear if you were listening to a real morse code transmission.To create an audible tone I tried fast flipping the wemos output pin on and off using digitalWrite(); - I couldn't get that to work.Perhaps PWM? I tried analogWrite(). It worked! On my PC with SDR# demodulating AM, I could hear an audible tone and so could my CW decoder app (http://ly3h.net/cw-decoder-logic/). It started printing my transmitted message. Joy!Important note!Before I post the code, I should mention that I did this experiment without an antenna on the TX module AND I'm far from 433mhz ISM devices - I scanned the band first before trying this - AND I'm licensed for 70cm. It would not be polite, and probably illegal in your country, to play with this in a populated area. Check your privilege. Don't be a spurious emitter; nobody likes that guy.Code:/*Morse Code bodge for the FS1000A*/#include <ESP8266WiFi.h>const int TXPIN = 2;char txString[] = "ALL UR BASE R BELONG TO US";void setup() {WiFi.forceSleepBegin(); // down the WiFi to save da powerz.pinMode(TXPIN, OUTPUT); // Initialize WeMOS D1 Mini D4 pin. Yup, I still don't fathom pin mappings, as 4 means 2 in this case.}void loop() {preamble(); // warble to signify begin message (for my own debug/amusement really. Not needed.)// The transmission of txString, char by char.for (int i = 0; i < sizeof(txString) - 1; i++) {char charToBang = txString;charToBang = toUpperCase(charToBang);bangChar(charToBang);}delay(5000); // Nice big pause of 5 secs between transmit string}/** Just for debug to signify the start of the sentence. Also, it sounds nice when demodulated to audio :)*/void preamble() {analogWrite(TXPIN, 180);delay(50);analogWrite(TXPIN,0);delay(50);analogWrite(TXPIN, 180);delay(50);analogWrite(TXPIN,0);delay(50);analogWrite(TXPIN, 180);delay(50);analogWrite(TXPIN,0);delay(50);analogWrite(TXPIN, 180);delay(50);analogWrite(TXPIN,0);delay(50);analogWrite(TXPIN, 180);delay(50);analogWrite(TXPIN,0);delay(50);analogWrite(TXPIN, 180);delay(50);analogWrite(TXPIN,0);delay(50);analogWrite(TXPIN, 180);delay(50);analogWrite(TXPIN,0);delay(85);// chirp?analogWrite(TXPIN, 220);delay(20);analogWrite(TXPIN,0);delay(10);analogWrite(TXPIN, 220);delay(20);analogWrite(TXPIN,0);delay(5000); // wait 5 secs after preamble}// send a dit to the TX on TXPINvoid dit() {analogWrite(TXPIN, 180);delay(100);analogWrite(TXPIN,0);delay(100);}void dah() {analogWrite(TXPIN, 180);delay(300);analogWrite(TXPIN,0);delay(100);}void newChar() {analogWrite(TXPIN, 0);delay(300);}void bangChar(char charToBang) {// Not the best code, but, to be fair, I'm s'it at coding and prototype-lazy! :)switch (charToBang) {// Letters (Up to 4 'bits' per letter)case 'A':dit(); dah(); break;case 'B':dah(); dit(); dit(); dit(); break;case 'C':dah(); dit(); dah(); dit(); break;case 'D':dah(); dit(); dit(); break;case 'E':dit(); break;case 'F':dit(); dit(); dah(); dit(); break;case 'G':dah(); dah(); dit(); break;case 'H':dit(); dit(); dit(); dit(); break;case 'I':dit(); dit(); break;case 'J':dit(); dah(); dah(); dah(); break;case 'K':dah(); dit(); dah(); break;case 'L':dit(); dah(); dit(); dit(); break;case 'M':dah(); dah(); break;case 'N':dah(); dit(); break;case 'O':dah(); dah(); dah(); break;case 'P':dit(); dah(); dah(); dit(); break;case 'Q':dah(); dah(); dit(); dah(); break;case 'R':dit(); dah(); dit(); break;case 'S':dit(); dit(); dit(); break;case 'T':dah(); break;case 'U':dit(); dit(); dah(); break;case 'V':dit(); dit(); dit(); dah(); break;case 'W':dit(); dah(); dah(); break;case 'X':dah(); dit(); dit(); dah(); break;case 'Y':dah(); dit(); dah(); dah(); break;case 'Z':dah(); dah(); dit(); dit(); break;case ' ':delay(1200); break; // Not sure if wise to have a big pause here. But, alas, this is the space bar!// numbers (always 5 'bits')case '1':dit(); dah(); dah(); dah(); dah(); break;// TODO: More numbers.}// pause after char output to show, possibly, that a new char is coming.newChar();} // end of bangChar()ConclusionI doubt this can be made in to a viable telemetry system, but it was fun to play with and, as a n00b, I learned a lot playing with it. If you want to pursue the long distance high altitude balloon telemetry side of things, look into Olivia and Contestia modulation. Also, scrap the FS1000A and get a module that can use side band. Bon vent!