Sending Periodic Hardware Status Updates Over RF

Hello,

I'm hoping you smart people can help me out here =]

A Little Bit of Background Information & What I'm Trying to Do

I am working on a project in which I would like to include the ability to send periodic system health / status updates back to base over RF.

My project already has radio transmit capability and audio output so ideally I'd like to make use of the existing hardware setup.

The transmission and audio set up I am using at the minute is very simple.

An arduino nano trips a relay which powers up the radio. Then the nano trips an Opto Isolator to put the radio into PTT and the audio is generated from pin 9 on the Nano.

Very Simple Requirements (From My Point of View at Least)

In my project I am hoping to include some self-monitoring (batt voltage, temp etc) and would like to have it take periodic readings throughout the day, store them and then transmit all the daily data back at a set time at the end of the day.

What I've Tried, What I've Done, What Happened etc...

I have gotten everything else I require for my project working. I use a real time clock to keep track of the real time and date. I have an SD card reader for reading from and writing to and I have all my TX hardware and code sorted. Everything from that point of view is working - and has had months of testing.

Where I am now struggling is finding the easiest and lightest way to transmit bursts or packets of data collected during the day.

I've been trying to adapt / modify / incorporate "out of the box" solutions such as MicroModem / Micro ARPS and many more of the popular TNC modem type software without much luck. Many of these programs were designed to run "stand alone" and are far too heavy and complicated for my needs so I've had no luck in separating out just the TX side.

The closest I've gotten to date has been using this very simple and lightweight library I found on GitHub called Arduino RTTY Transmitter. GitHub - farroid/arduino-rtty-transmitter: Simple RTTY transmitter for HAB and other applications

It does exactly what it says on the tin but not exactly what I want and I'm not quite sure how to modify it to do what I need....

The Arduino RTTY Transmitter Library will allow me to pass text (string?) messages to the TX function for it to "encode" into RTTY tones but it will not accept variable data directly e.g.

RTTY.tx("Hello, this is a test message"); Will Work
RTTY.tx(variableValue); Will Not Work.

Obviously the TX function wasn't designed to receive and handle data in this way and I'm not entirely sure what to do to alter it.

In Closing

My programming knowledge is very very rusty these days - I'm practically back at noob level.

I've not done any real in depth programming for a good 5 years or more besides tinkering with simple things in the Arduino IDE here and there. To look at my work now, you wouldn't believe I went to college and passed C and C++ programming with flying colours.

For my final project I wrote a stock trading game in C which earned me a distinction. Amazing how the knowledge slips away when not used frequently. :frowning:

Anyway....

As far as my latest project goes, I'm now stuck trying to alter that RTTY Tx function or possibly write a second function for transmitting variable data.

To be honest, I'd rather use a more up to date and faster data TX mode - something that only takes around 10 - 15 seconds or less to transmit the data but this RTTY library was all I could get to work.

I'm certainly not back at the skill level necessary to write my own code from scratch in any reasonable length of time. These days progress is slow and I struggle to get my programs to work without constantly going back to the reference books.

So this is the function I need to modify so I can pass the data stored in several variables to it and encode them into RTTY.. e.g battery voltage, battery current, temperature etc.

void RTTY5::tx(char* string)
{
    char c = *string++;
    byte index = 0, pos = 0;
    byte shift = 0;
    
    while (c != '\0')
    {
        char* index = strchr(BAUDOT_FIGS, c);
        if(index != NULL) {
            pos = index - BAUDOT_FIGS;
            if(pos > 2 && shift != 1) {
                shift = 1;
                rtty_txbyte(BAUDOT_SHIFT_FIGS);
            }
            rtty_txbyte (baudot[pos]);
        } else {
            c = toupper(c);
            index = strchr(BAUDOT_LTRS, c);
            pos = index - BAUDOT_LTRS;
            if(pos > 2 && shift != 2) {
                shift = 2;
                rtty_txbyte(31);
            }
            rtty_txbyte (baudot[pos]);
        }
        c = *string++;
    }
}

I've spent a fair few hours starring at that function running through it over and over like a loop in my head, breaking it down, following it through step by step.

It looks to me like it gets passed my message text from my main program loop RTTY.tx("message") and then char c = *string++; I think is basically incrementally (++) scrolling through that string, char by char and assigns each char in the string to the variable C while keeping an index position?

Then the program goes into a while loop while (c != '\0') which it will continue to loop through until it comes to \0 in the string which signals end of the string \ new line \ empty character?

So I can pretty much read it and follow it logically (with a few parts I don't fully understand in there) but I just can't get my head around how to adapt it.

I know anything I try at this point won't be nearly as simple and elegant so I'm reaching out at this point for some assistance.

In the meantime, I'm going to continue to work the problem or try my best to find and adapt something better - preferably more up to date and faster.

Thanks in advance and sorry for the lengthy post. I was just trying to put down as much relevant information as I could.

:slight_smile:

You seem at least to have got something which works:

RTTY.tx("Hello, this is a test message"); Will Work
RTTY.tx(variableValue); Will Not Work.

If it enough to send the data as a series of separate calls to RTTY.tx you could simply do something like this:

RTTY.tx("Hello, this is a test message"); 
RTTY.tx( itoa( variableValue) ); //    variableValue is an int or use equivalent of itoa() for the required datatype.

If you don't like that, you can assemble the whole message in a buffer (char array, null terminated) and send that.

RTTY.tx( itoa( variableValue) ); //    variableValue is an int or use equivalent of itoa() for the required datatype.

It would, of course, be better to use itoa() correctly. The itoa() function takes three arguments, not one.

Thank you!

Yes, sending separate calls to RTTY.tx would be perfectly fine.

This has pointed me in the direction of something I can work on / with so thank you for that.

I'll have a little play around and see what happens now :slight_smile:

Thank you!

PaulS:

RTTY.tx( itoa( variableValue) ); //    variableValue is an int or use equivalent of itoa() for the required datatype.

It would, of course, be better to use itoa() correctly. The itoa() function takes three arguments, not one.

Ah yes. That is of course correct. Here it is. A bit clumsier than I originally wrote:

char buffer[8] ;   // at least 1 byte larger that the largest string you convert.
itoa( variableValue , buffer, 10 ) ; // char *  itoa ( int value, char * str, int base );
RTTY.tx( buffer ); //    variableValue is an int or use equivalent of itoa() for the required datatype.

sprintf() might also be a better alternative if the structure of the output is more or less constant.

pi_and_chips:
My project already has radio transmit capability and audio output so ideally I'd like to make use of the existing hardware setup.

......

Where I am now struggling is finding the easiest and lightest way to transmit bursts or packets of data collected during the day.

If your struggling, and you want help, then more details on the location, where the TX and RX antennas are, and the terrain and distances involved are required.

I would say that although I have used RTTY over very long distances it would be a long way from my first choice as a 'simple' method for getting data from A to B. The equipment at the receiving end tends not to be simple, low cost or power effecient.

Hey guys,

I just wanted to say thanks again.

itoa() was enough to point me in the right direction and it worked a treat. The program sends variable data over RTTY now with no problem.

srnet:
If your struggling, and you want help, then more details on the location, where the TX and RX antennas are, and the terrain and distances involved are required.

I would say that although I have used RTTY over very long distances it would be a long way from my first choice as a 'simple' method for getting data from A to B. The equipment at the receiving end tends not to be simple, low cost or power effecient.

Hi srnet,

Thanks for replying.

I totally agree with your thoughts on using RTTY to send data. It wasn't my first choice but was the only "off the shelf" solution I could get working that was of a small size, simple to set up and relatively easy to incorporate into my program.

To receive the data back, I had planned on using my UHF/VHF ham radio at home and feed the audio output from that to my laptop for "decoding" using MMTTY.

My project will take readings every hour for 15 hours per day and store them ready for transmission later.
I plan to send the data back in the format of something like:-

!SYSTEM HEALTH STATUS!
Voltage: 12.9, 12.9, 12.8, 12.8, 12.8, 12.7, 12.7....
Amps: 6, 6, 5.59, 5.59, 5.5......
Charge Voltage: 14.0, 14.1, 13.2, 12.0......
!MESSAGE ENDS!

Etc.

If there's a more reliable mode I can adapt / use, I would surely jump at the chance of any help / suggestions you can offer.

This is actually a part of a larger club project / fun learning challenge I'm working on with a small, local Amateur Radio club I am a member of. It's basically a long duration remote monitoring station. I doubt it will actually get put into service apart from as an educational tool - it's more of a fun group activity and learning exercise / concept.

The idea behind this project is to get everyone involved, learning and working as a group (regardless of technical level) towards something interesting and functional at the end.

The couple of advanced guys we've got at the club aren't really all that clued up with digital electronics - they're respectfully old school valves and analogue. Having dabbled with Arduino I thought it would be something it could handle relatively easily.

The majority of our membership is made up of foundation class license holders, like myself or people looking to get into ham radio and get a foundation license. Not many have an understanding of electronics yet but most are interested enough to take part and willing to learn.

The project was ultimately broken down into several tasks and I was assigned with the task / challenge of creating the electronics / software required to power up the transmitter, put it into PTT and transmit the collected daily data back to base, "somehow" and then power everything off again.

With this monitoring station being remote and long duration, it will be battery powered and topped off by either by means of wind or solar charging by way of a charge controller. This is a task assigned to another project member but goes hand in hand with one of the projects top requirements, Low Power Consumption, Maximum Life.

Since my side of the project is pretty much the "brain" of the whole device, I've made use of the Atmega's sleep and low power capabilities. The atmega now spends most of it's time sleeping and only wakes periodically to see if it needs to do anything. The last time I used low power on an Atmega project, it impressively barely took any power at all while sleeping so I'm hopeful I can expect the same with this project.

I've yet to properly measure the power consumption or tweak around with what more I can save. I'll do that once everything on my side of the project is more or less finalised and working reliably and I'm happy with it.

Up to now, this is where I'm at with my side of the project. So far my circuit(s) and software are doing everything as they should, when they should all more or less with down to the second timing - so I'm pleased with that. I'm just not overly keen on using RTTY as a means of sending data over RF myself either.

I am happily open to all suggestions regarding the data mode transmission.

Sorry for the lengthy reply, I get a little carried away with my explanations.

Also I have another little problem I couldn't get my head around. Or rather had another little problem...

With everything progressing so well, I did try and get a little fancy with this project but it didn't work out and I'm not entirely sure why.

Basically, I've got a DFPlayer Mini module and I thought I'd incorporate that into my design for a little added creativity and novelty value. I was going to use the DFPlayer Mini module to play an audio message prior to the RTTY data transmission. Something like "This is a Remote Beacon Test Transmission. Data to Follow" and then have the data transmitted a second or two later.

The problem I had was combining both the audio signals from both the DFPlayer and the RTTY Tone pin together into what will be the audio input on the transmitter. For the purposes of testing I am using a speaker to simulate what would be the transmitter's audio input.

This resulted in a substantial drop in volume on both audio signals and I sort of vaguely understand why but I'm not sure what to do to resolve it.

The circuit for just this side of things is very simple:-

I have my entire prototype mocked up on breadboard with everything running from the same power supply source - as it would be if it were running when fully completed i.e. from one battery source. The power supply being use is a typical breadboard power supply fed by a 12V plug-in-the-wall power pack. In the completed project, some form of low power dc-dc converter is planned to regulate the battery voltage down to 5 Volts

So in the circuit, the DFPlayer and Atmega both share the same regulated 5V and GND supply.

There are two software serial wires coming from the DFPlayer's RX/TX pins which go to two digita software serial pins on the atmega - each with 1K resistors in series as per the recommendations.

The two final wires from the DFPlayer are Spkr + and Spkr -

And then we have a lone RTTY audio signal wire coming from a digital pin on the atmega. I have placed a 120 Ohm resistor in series with this signal wire to protect the digital pin when connecting to a speaker as per recommendations.

So what I've been doing is taking the actual Spkr - wire from the speaker and connecting it to the spkr - pin on the DFPlayer.

Then I take the RTTY audio signal wire and connect it to the spkr + directly on the speaker.

Fine, no problem, I hear nice strong RTTY tones.

Then the minute I connect the Spkr + pin from the DFPlayer to the same point (i.e. the DFPlayer Spkr + Pin together with the RTTY Audio Signal and the speaker +) all combined, everything gets pulled down / the volume is reduced.

I'm not too clued up with this sort of thing but I'm thinking either there's a grounding issue going on in the sense that the RTTY audio signal wire is a lone signal wire coming from a digital pin of the arduino and does not have a companion ground wire with it and through the "witchcraft of electronics" some "magic" is going on where the RTTY audio signal wire is getting some sort of weak ground of sorts through the DFPlayer module back to the 5V Supply ground - which is its rightful companion ground wire?

Whereas the DFPlayer does have a true audio companion ground (as I think of it) because it has a dedicated spkr + and spkr - pins and can physically complete a strong circuit - if you will?

Or my second supposition is that the loading is too great somewhere along the line and it could be that the speaker loading being shared is the reason for pulling everything down?

Of course, it'll likely turn out I was way off the mark - as usual lol.

I should point out before anyone asks that I am not trying to play both the audio and the rtty tones at the same time. Just one or the other. lol

I spent hours last night googling away trying to find a solution and trying various combinations of suggested resistors and capacitors without success. The closest I got was getting the audio of one signal to be louder than it should have been while the other was virtually non-existent.

Most of my attempts last night were pretty much stabs in the dark using solutions to problems that were quite similar to my own which I found through Google. Not fully understanding the problem I'm not entirely sure where to start. Probably a little beyond my comprehension at this point in time.

Ultimately I admitted defeat and sought the advice of another club member last night via email and they suggested trying a separate 5V power supply just for the DFPlayer. A perfectly reasonable suggestion.
So I disconnected the DFPlayer from the same sources as the Atmega and connected the DFPlayer exclusively to a separate 5V source.

Well, ummm, the DFPlayer didn't like that idea very much. Having set everything up for a test run, I sat an waited for it to all power up and do it's thing. Sure enough it powered up and moments later I heard the sound of tiny pops and crackles shortly followed by a distinctly horrible burning electronics smell.
I looked down and saw tiny wisps of smoke emerging from the DFPlayer and immediately started to flap like a headless chicken pulling wires and flipping switches trying to preserve the "precious things" lol.

The DFPlayer was toasted and that was the end of that. Fortunately everything else survived.

The voice module idea most likely wont make it into the final construction since it was purely a novelty idea and wasn't a requirement - and I can't seem to get the two audio signals to work together.

But I would still be interested for future reference as to what the problem is and how it could be rectified.

Thanks again!!

Well a few years back I used an RFM22B as the comms device for a satellite. The RFM22B is small FSK Data device (15mmx15mm) and cheap, clones are around £2. Max power output is 100mW.

I knew the RFM22B could work as a simple FM Morse beacon and would very likley be heard on the ground on UHF HAM handhelds, but getting data back on only 100mW ?

Using a Yaesu FT817 as the receiver (no slouch at UHF) I compared the sensitivity of using the RFM22B to send AFSK RTTY and FSK RTTY at 100baud. The FSK RTTY had about a 10dB 'gain' over AFSK RTTY so would cover around 3 times the distance. FSK RTTY was incorporated into the design and proved to be very effective, it was regularly picked up at LOS distances of circa 2,200km.

However the reception of the FSK RTTY is tricky and needed relativly complex, power hungry and expensive equipment, although this is equipment that most Amateur radio enthusiasts would already have.

The reason for mentioning this is that recently I compared the effectivness of LoRa devices versus FSK RTTY, using the same FT817 as before. The LoRa modules were around 6dB better or twice distance.

The FSK RTTY HAM radio setup cost circa £1000, but the £10 LoRa receiver was a lot better, for data.

Definetly consider LoRa, not difficult to drive.

Voice on 144.390 is not in the band plan for 2M.

aarg:
Voice on 144.390 is not in the band plan for 2M.

In some parts of the World, the UK for instance, you cannot use the amateur bands for data logging type applications, even if the 'user' is a license holder. The restriction is the amateur bands are intended to be used for communication between license holders, so you cannot normally broadcast information to yourself.

srnet:
In some parts of the World, the UK for instance, you cannot use the amateur bands for data logging type applications, even if the 'user' is a license holder. The restriction is the amateur bands are intended to be used for communication between license holders, so you cannot normally broadcast information to yourself.

Yes, autonomous trackers and telemetry from an unattended transmitting station are technically not permitted under part 97 rules in the USA because they are one-way communications and there is no provision for remote station control.

It's just that nobody cares.

I just wanted to say thank you again to everyone for all the invaluable help.
My side of the project is not far from complete enough to think about etching out a prototype board. Something I thought would be a few more weeks away with the problems I was having. I've just got one more system to design, build and test.

Also, I wouldn't worry too much about licensing conditions etc because as I've mentioned, this is purely a group technical exercise and such it is highly doubtful that this project will ever see live active service without conforming first.
The whole project is more about the journey than the destination :slight_smile:

And finally, I really wanted to update this thread for the sake of consistency and future reference (for myself or anyone else that may be reading this).

First of all, while it wont be implemented in my final design, my curiosity got the better of me and I just had to figure out why the DFPlayer SPKR Audio Output didn't like sharing the speaker I was using with the RTTY PWM Tone Audio pin from the Arduino without the volume of both signals dropping substantially.

This little problem has been bugging me in the back of my mind since I encountered it and being me, I just had to find a solution whether or not it is going to be used.

Again I spent some time fiddling around with various capacitor and resistor values and arrangements (this time with some educated guidance of another project member) and we couldn't get both devices to share the speaker (not at the same time of course).

In the end, I settled on an idea that I had previously had but put to the back of the shelf because it seemed too simple and clunky.

The solution which I settled on in the end (at the cost of a little more power consumption when fully active) was to use a 5v relay to switch between one audio signal source or the other.
I pretty much ended up with an identical copy of my transmitter power on/off circuit. A relay which is energised by a transistor controlled by a pin on the arduino named RTTY_EN.

I've wired one side of the speaker to the DFPlayer SPKR - and the SPKR + to the COMMON PIN on the relay. The DFPlayer SPKR + goes to the normally closed side of the relay while the RTTY Audio Signal wire goes to the other.

Then when I want to TX RTTY, I can write the RTTY_EN pin high, send the RTTY and de-energise the relay to return to the default device - the DFPlayer.

AND LASTLY, another problem popped up which I didn't foresee when sending RTTY data and that was handling decimal values.

When I tried passing a decimal temperature value to the itoa function for converting into char for the RTTY TX function to work with, I completely forgot that it wouldn't output a decimal value back.

I spent a good while working on my temperature code thinking that it was responsible for outputting the wrong data type. So instead of getting a value of 21.4 transmitted via the RTTY TX function, it would just send out a whole number and lose the decimal place value.

Eventually the answer clicked in my head that because I was converting to char, I couldn't pass it a float value without a little trickery.

Thanks to the suggestion of using itoa() from the guys here to begin it with gave me a point of reference from which to find a new solution for passing decimal values without having to rip apart or start rewriting the RTTY library I'm using.

I came across this solution on another website for doing what I wanted in Arduino.

Basically, the conversion is very similar and so it didn't take much adapting of my code to get it to work.

instead of using itoa() in the RTTY.TX function, I use dtostrf() like so..

char rttybuf [5];
RTTY.tx(dtostrf(temp, 4, 1, rttybuf));

instead of

char rttybuf[5]
RTTY.tx(itoa(temp, rttybuf, 10));

So barely any work at all to modify the old conversion code I was using to the new.

The last system I need to get designed, tested and built is the battery health (voltage, current etc) and charge monitoring sensing system. I want to monitor, read and log all the data I can about the state of the battery including charging data.

The idea is that the unit will wake up every hour to take readings from all of its sensors. It will store each reading, probably in a 2D array (maybe stored in in EEPROM for the sake of any unexpected power losses or resets)

Then at the end of it's operating period, it should scroll through the arrays of data sending them back as RTTY.

E.g.

Tmp: value1, value2, value3....
Baro: value1, value2, value3....
Light: value1, value2, value3....
Volt: value1, value2...............

And so on.

I've deliberately left this part til last because from my perspective, it is the most tricky.

The circuit that is looking the most promising is a voltage divider on the 12V battery with a 2N7000 mosfet tied to a pin on the atmega to switch the divider into circuit only when testing to save power.

However I'm not sure how much information that alone will give me. I would like to monitor as much information about the battery and charging as I possible can to give me the most complete picture.
How much power and voltage is the solar panel giving out, is the battery charging, how much charge is it getting...

As much information as I can gather for processing to give me the most complete picture, the better.

Thanks again for all the help. I wouldn't be this far without it!

pi_and_chips:
An arduino nano trips a relay which powers up the radio. Then the nano trips an Opto Isolator to put the radio into PTT and the audio is generated from pin 9 on the Nano.

I might switch that relay and opto isolator, but it doesn't trip it. A circuit-breaker would be tripped, and once
tripped it needs physical action (press the reset lever) to reset it. Tripping is a feature of protection devices,
not normal circuit operation, it implies a fault has developed.

Talking about the actual problem, I would recommend using some sort of checksum or error detection
mechanism if sending data over the air, since you will inevitably get garbled reads on occassion and
should be able to filter those out.