Demo : Controlling a PICAXE by using Morse Code from smartphone app


Senior Member

This post came about when I re-thought my 'Option 4' in this thread :

The idea back then was to write an app that could flash the screen on a phone to set the node number of a slave, and send the physical co-ordinates to the Master via Bluetooth. This would need a Bluetooth module and a lot of phone programming.

It would be much better if an app already existed. Well, it does !

There are now plenty apps in the app stores that can send Morse Code via the camera flash.

The phone apps ( I used TESLA LED from the Android app store ) let you type in text, which it then sends as flashes of light.
A photodiode is connected to the PICAXE, and then PICAXE decodes the pulses of light into ASCII characters, for use as you want.

This demo just uses the letters RGB to operate 3 LEDs, but it could be used to send a room name and sensor number to a slave node.

The photodiode I used was not very sensitive, that's why the phone is lying directly on it. A better photodetector and maybe a lens would give much better performance.

One thing to watch with ( at least with TESLA LED ) is that sometimes the app get the timings wrong, so bad you can see and hear it. It only seem to happen when the app has been sending continuously for about 30 mins, probably due to some memory garbage collection or something.

I don't know if this is of any use to anybody, but I enjoyed proving it can be done !.



' Decode morse generated by 'TESLA LED' app from Android playstore
' Uses Magic Morse algorithm (c) 2011 by Mickey R. Burnette

#picaxe 28X2

' ================================================================================
'                    Magic Morse tables stored in EEPROM
' ================================================================================
' All mappings are 5-bit with exception of ", . ? @" which are 6-bit
' mappings squeezed into the 5-bit space by dropping the 6th bit
EEPROM 0, (0,"E","I","S","H","5",0,0,0)
'EMPTY 6, 7, 8
EEPROM 9, ("T","N","D","B","6",0,0,0,0)
'EMPTY 14, 15, 16, 17
EEPROM 18,("A","R","L",0,0,0,0,0)
'EMPTY 21, 22, 23, 24, 25
EEPROM 26,("M","G","Z","7",0,0,0,0,0)
'EMPTY 30, 31, 32, 33, 34
EEPROM 35,("U","F",0,0,0,0)
'EMPTY 37, 38, 39, 40
EEPROM 41,("i",0)				'i == INVITE
EEPROM 43,("K","C",0,0,0,0,0,0)
'EMPTY 45, 46 ,47, 48, 49, 50
EEPROM 51,("W","P",0,0,0,0,0,0)
'EMPTY 53, 54, 55, 56, 57, 58
EEPROM 59,("O",0)
EEPROM 61,("8",0,0,0,0,0,0)
'EMPTY 62, 63, 64, 65, 66, 67
EEPROM 68,("V","u",0,0,0,0,0,0)	'u == UNDERSTOOD
'EMPTY 70, 71, 72, 73, 74, 75
EEPROM 76,("X","/",0,0,0,0,0,0,0,0,".",0,0,0,0,0)	'SLASH=77 PERIOD=86
'EMPTY 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91
EEPROM 92,("Q",0,0,0,0,0,0,0,0)
EEPROM 101,(0,"?",0,0,0,0,0)		'QUESTION MARK=102
'EMPTY 93, 94, 95, 96, 97, 98, 99, 100, 102, 103, 104, 105, 106, 107
EEPROM 108,("Y",0,0,0,0,0,0,0)
'EMPTY 109, 110, 111, 112, 113, 114, 115
EEPROM 116,("J",0,0,0,0,0,0,0,0)
'EMPTY 117, 118, 119, 120, 121, 122, 123, 124
EEPROM 125, ("9",0,0,0,0,0,0,0)
'EMPTY 126, 127, 128, 129, 130, 131, 132
EEPROM 133, ("4") : EEPROM 134, ("(") : EEPROM 135, ("c") : EEPROM 136, (")")
EEPROM 137, (" ") : EEPROM 138, ("M") : EEPROM 139, (".") : EEPROM 140, ("R")
EEPROM 141, (".") : EEPROM 142, ("B") : EEPROM 143, ("U") : EEPROM 144, ("R")
EEPROM 145, ("N") : EEPROM 146, ("E") : EEPROM 147, ("T") : EEPROM 148, ("T")
EEPROM 149, ("E")

EEPROM 159, (100)	' DIT timing variable
EEPROM 162, (">",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)	' > == STARTING
'EMPTY 163 - 181
EEPROM 182, ("@",0,0,0,0,0,0,0,0,0,0,0,0,0,0)			' @ ==182
'EMPTY 183 - 196
EEPROM 197, ("3")

' Following Block of EEPROM available for customizations / future options-enhancements
EEPROM 198, (0) : EEPROM 199, (0) : EEPROM 200, (0) : EEPROM 201, (0)
EEPROM 202, (0) : EEPROM 203, (0) : EEPROM 204, (0) : EEPROM 205, (0)
EEPROM 206, (0) : EEPROM 207, (0) : EEPROM 208, (0) : EEPROM 209, (0)
EEPROM 210, (0) : EEPROM 211, (0) : EEPROM 212, (0) : EEPROM 213, (0)
EEPROM 214, (0) : EEPROM 215, (0) : EEPROM 216, (0) : EEPROM 217, (0)
EEPROM 218, (0) : EEPROM 219, (0) : EEPROM 220, (0) : EEPROM 221, (0)
EEPROM 222, (0) : EEPROM 223, (0) : EEPROM 224, (0) : EEPROM 225, (0)
EEPROM 226, (0) : EEPROM 227, (0) : EEPROM 228, (0)
'EMPTY 198 - 228	' 31
EEPROM 229, ("2",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
'EMPTY 230 - 244	' 15
EEPROM 245, ("1",0,0,0,0,0,0,0)
'EMPTY 246 - 252	' 7
EEPROM 253, ("0",0,0)
'EMPTY 254, 255	' 2

' ================================================================================
' ||                         End of Magic Morse tables                          ||
' ================================================================================

' ================================================================================
' ||                         Symbols                                            ||
' ================================================================================

SYMBOL DitDah     = b1	' Used in MM algorithm
SYMBOL Point      = B2	' Used in MM algorithm
SYMBOL RXedChar   = B3	' ASCII value after decoding morse
SYMBOL PulseNow 	= b4	' Current state of input
SYMBOL PulseMem 	= b5	' Memory for 1-shot
SYMBOL EoWflag	= b6	' Set when end of word detected

SYMBOL time_0   	= w4	' Duration of idle time, ie. gap between Dits and Dahs
SYMBOL time_1   	= w5	' Duration of active time, ie. Dit or Dah

SYMBOL DITtimv	= w6	' Max length of a Dit
SYMBOL EoLtimv	= w7	' End of Letter timer value
SYMBOL EoWtimv	= w8	' End of Word timer value

SYMBOL PhotoIn 	= pinC.2	'The signal from the photodetector
SYMBOL actvLED 	= C.4		' Activity LED, flashes in time with input

SYMBOL BLUled 	= pinA.0	'
SYMBOL GRNled 	= pinA.1	'	Demo LEDs
SYMBOL REDled 	= pinA.2	'

' ================================================================================
' ||                         Code starts here                                   ||
' ==============================================================================

setfreq m16		' Run at 16MHz
settimer 65500	' Preset timer reload to make timer tick faster

low A.0	'
low A.1	' Demo LEDs
low A.2	'

' Set morse speed parameters
DITtimv = 450		' Max length of a Dit
EoLtimv = 700		' End of Letter time
EoWtimv = 1000		' End of Word time

do	' Main loop
	PulseNow = PhotoIn	' Get current state of input pin
	if PulseNow <> PulseMem then  ' If state changed since last scan,
		if PulseNow = 0 then		' 0 = Active, Dit or Dah
			high actvLED		' Turn on activity LED
			time_0 = timer		' Record length of last idle
			timer = 0			' Reset timer
			if time_0 > EoLtimv then	' End of letter time	
				DitDah = DitDah + Point	' Complete the two-part pointer 
				READ DitDah, RxedChar	' Read mapped character from EEPROM
				sertxd(RxedChar," ")	
				if time_0 > EoWtimv then	' End of word
					EoWflag = 1
					EoWflag = 0
				point = 0			' Reset point count
				DitDah = 0			' Reset address workbyte
				gosub ProcessChar		' Call routine to process RXedChar
		else					' 1 = Inactive, line idle
			low actvLED			' Turn off activity LED
			time_1 = timer		' Record length of last flash
			timer = 0			' Reset timer
			inc point			' increment point on any Dit or Dah
			if time_1 < DITtimv then 	' Dit, do nothing
			else 				 	' Dah, update address
				Select Case Point
					Case 1 : DitDah = DitDah OR %00001000
					Case 2 : DitDah = DitDah OR %00010000
					Case 3 : DitDah = DitDah OR %00100000
					Case 4 : DitDah = DitDah OR %01000000
					Case 5 : DitDah = DitDah OR %10000000
				End Select 

      	PulseMem = PulseNow	' Update memory
	endif ' End of state changed logic

loop	' End of main loop

' ================================================================================
' ||                         Subroutines                                        ||
' ================================================================================

' Put code here to handle the received data as each character is decoded.
' The EoWflag is set if the character is also the end of a word.

if RXedChar = "B" then
	inc BLUled		' Toggle blue led

if RXedChar = "R" then
	inc REDled		' Toggle red led

if RXedChar = "G" then
	inc GRNled		' Toggle green led



Senior Member
BRAVO! Awesome concept and execution of a creative, offbeat concept. Supported by a succinct one-minute video demonstration. Perfect. And a neat new way to interface with smart phones.

Genius is at hand!


Senior Member
Ir perhaps?

Clever -but such flashing LEDs may be prone to false triggering, and of course a tad indiscrete! Consider Infrared instead using inbuilt Picaxe commands & a plug in Android earphone IR dongle?


Well-known member
Here's an app for Apple's iPhone/iPad that can be used like Buzby's description of the "Tesla LED" app for Android. Free to download, but with in-app purchases available. It is called "Morse Code Guru Lite" in the Apple app store.

Will trigger the flash and/or speaker with typed text or typed Morse code.

manuka, indiscreet or not, this is still a cheap way to input into a device, which is something I'm dealing with right now.


Senior Member
Hi All,

Thanks for the compliments, it makes all my efforts worthwhile.

The code was just written as a 'proof of concept', and as such it needs a few improvements. I might get round to doing them one day.

Note, if you use a different app you will need to change the 3 values in the morse speed parameters. The code below will help you determine what they should be.
When it runs it prints the lengths of flashes and gaps. Set your phone app sending 'AB' repeatedly. This creates a flash sequence of Dits and Dahs, with an EndOfLetter gap between them, an and EndOfWord gap at the end of each repeat. Copy the first column ( Dit & Dahs ) into Excel, then make a bar graph. From this graph you can see the difference between a Dit and a Dah, and select the 'DITtimv' accordingly. Repeat with the second column, which will give the 'EoLtimv' and 'EoWtimv' values.

[color=Green]' Measure morse generated by app from store[/color]

[color=Navy]#picaxe [/color][color=Black]28X2[/color]

[color=Green]' ================================================================================
' ||                         Symbols                                            ||
' ================================================================================[/color]

[color=Blue]SYMBOL [/color][color=Black]PulseNow   [/color][color=DarkCyan]= [/color][color=Purple]b4  [/color][color=Green]' Current state of input[/color]
[color=Blue]SYMBOL [/color][color=Black]PulseMem   [/color][color=DarkCyan]= [/color][color=Purple]b5  [/color][color=Green]' Memory for 1-shot[/color]

[color=Blue]SYMBOL [/color][color=Black]time_0     [/color][color=DarkCyan]= [/color][color=Purple]w4  [/color][color=Green]' Duration of idle time, ie. gap between Dits and Dahs[/color]
[color=Blue]SYMBOL [/color][color=Black]time_1     [/color][color=DarkCyan]= [/color][color=Purple]w5  [/color][color=Green]' Duration of active time, ie. Dit or Dah[/color]

[color=Blue]SYMBOL [/color][color=Black]PhotoIn    [/color][color=DarkCyan]= [/color][color=Purple]pinC.2    [/color][color=Green]'The signal from the photodetector[/color]
[color=Blue]SYMBOL [/color][color=Black]actvLED    [/color][color=DarkCyan]= [/color][color=Blue]C.4       [/color][color=Green]' Activity LED, flashes in time with input

' ================================================================================
' ||                         Code starts here                                   ||
' ==============================================================================[/color]

[color=Blue]setfreq m16       [/color][color=Green]' Run at 16MHz[/color]
[color=Blue]settimer [/color][color=Navy]65500    [/color][color=Green]' Preset timer reload to make timer tick faster[/color]

[color=Blue]do    [/color][color=Green]' Main loop
      [/color][color=Black]PulseNow [/color][color=DarkCyan]= [/color][color=Black]PhotoIn      [/color][color=Green]' Get current state of input pin
      [/color][color=Blue]if [/color][color=Black]PulseNow [/color][color=DarkCyan]<> [/color][color=Black]PulseMem [/color][color=Blue]then  [/color][color=Green]' If state changed since last scan,
            [/color][color=Blue]if [/color][color=Black]PulseNow [/color][color=DarkCyan]= [/color][color=Navy]0 [/color][color=Blue]then          [/color][color=Green]' 0 = Active, Dit or Dah
                  [/color][color=Blue]high [/color][color=Black]actvLED            [/color][color=Green]' Turn on activity LED
                  [/color][color=Black]time_0 [/color][color=DarkCyan]= [/color][color=Purple]timer          [/color][color=Green]' Record length of last idle
                  [/color][color=Purple]timer [/color][color=DarkCyan]= [/color][color=Navy]0               [/color][color=Green]' Reset timer
            [/color][color=Blue]else                          [/color][color=Green]' 1 = Inactive, line idle
                  [/color][color=Blue]low [/color][color=Black]actvLED             [/color][color=Green]' Turn off activity LED
                  [/color][color=Black]time_1 [/color][color=DarkCyan]= [/color][color=Purple]timer          [/color][color=Green]' Record length of last flash
                  [/color][color=Purple]timer [/color][color=DarkCyan]= [/color][color=Navy]0               [/color][color=Green]' Reset timer

            [/color][color=Black]PulseMem [/color][color=DarkCyan]= [/color][color=Black]PulseNow     [/color][color=Green]' Update memory
      [/color][color=Blue]endif [/color][color=Green]' End of state changed logic[/color]

[color=Blue]loop  [/color][color=Green]' End of main loop[/color]
I've not tested all of the Morse symbols in the MM lookup table, TESLA LED can't send some of them , so I can't vouch for the accuracy of the table.
( Looking at it in hindsight, it would probably have been just as easy to write my own tables. )




Senior Member
One problem I can see with IR blasters that emulate Sony etc. is that they don't send text.
( And if they did send text, you would have to decode the protocols of each supplier. Morse is universal. )

A driving force behind this experiment was to see how to get strings, such as room names, into a PICAXE easily and at low cost.


Technical Support
Staff member
Note, if you use a different app you will need to change the 3 values in the morse speed parameters. The code below will help you determine what they should be.
By repeatedly sending "C" - dash-dot-dash-dot - you should be able to auto-calibrate the timing in a setup mode. Half way between min and max present periods should be enough to discriminate between dot and dash. Some of the techniques used when I was measuring IR remote codes may come in useful -

Full marks for a novel solution.


Senior Member
Hi hippy,

I'm working on exactly something like that now, but I'm beginning to distrust this TESLA LED app.

From Wikipedia, "The duration of a dash is three times the duration of a dot. Each dot or dash is followed by a short silence, equal to the dot duration. The letters of a word are separated by a space equal to three dots (one dash), and the words are separated by a space equal to seven dots. The dot duration is the basic unit of time measurement in code transmission."

In the picture below the blue columns are dots and dashes, The sequence is repeated '50', ie '.....-----'.


It doesn't look to me that TESLA LED is sticking to the rules. What do you think ?

( The app does have various methods of altering the LED driver logic, maybe it's better with with a different one. I'll try tomorrow. )




Senior Member
Most excellent. Buzby is catching Morse fever. This time next year, he'll be a 60 WPM licensed Ham radio operator, spending all his waking hours on his 40 meter QRP CW rig. Never to be seen here again.

All future posts in this thread must be in Morse only. Catch you guys on a QSO soon.

--... ...-- --- --
-.. .
. .-. -.-. ---
-.- -- -.... -.. ...


Senior Member
No idea about software support on the phone side, but just from a technical point of view Baudot is worth to consider.



Senior Member
Guys- I'm well up with recent smartphones having in built IR blasters. It's the "oldies but goodies" (such as the still popular Samsung S3 etc) that I'd in mind for headphone jack or OTG ( USB style "On The Go") IR.

A good decade back, & hence pre today's BT/WiFi & smart phone approaches, inbuilt PICAXE TX/RX 38 kHz IR handling & cheap Vishap style sensors revolutionised "wireless" signal & control. Stan. (dah dit dah - dah dit)


Senior Member
She was only the telegraphers daughter but she did it, did it, did it, ...sorry, children might be viewing this site :)


Senior Member
Phone to picaxe...I got a dog repel app, and you can vary freq, top freq hear clicks (quantisizeation noise?)
Connect piezo mic/speaker to pin.
check for 2 continuous tones
peasy,init..not in reality.


Senior Member
Phone to picaxe...I got a dog repel app, ...Connect piezo mic/speaker to pin ... check for 2 continuous tones ... peasy,init..not in reality.
Actually it is easy, but not very useful.

The great advantage of Morse is that it is available on lots of devices, and was designed specifically for sending text.

Now we have a demo of decoding flashing Morse, it should be easy to modify for other sources, such as touch-pad Morse. ( That's a zero dollar solution, but you'd need a steady fist. )

For something simpler, how about my next half baked idea, Morse flash your outside Christmas lights !.




Senior Member
No idea about software support on the phone side, but just from a technical point of view Baudot is worth to consider.
The problem with BAUDOT is you need to keep track of the NUMBER/LETTER/WHATEVER shifts. This may have been beneficial when the decoding had to be done with electro-mechanical devices, but now we've got electronics we can simplify the operator's job and use a coding method with a more natural flow.

What impressed me with my idea was that I could send complex data without any programming of the phone, and $1 hardware on the PICAXE.
It's a really cheap way of changing settings in the field, or providing a PIN number for a lock.

What I need to find now is an app that can read Morse via the camera. Think what we could do with that !.




Senior Member

I tried Morse Talk on my Sony and Samsung, but it didn't do anything other than send, no sign of how to read Morse at all.

Then I tried Morse Tools, and it's a cracker. It can receive sound or light, and send light, sound, or vibration, and has a good interface.

I've got a really half baked idea for an experiment in mind, in fact it's so off the wall I think I might need a psychiatrist.

It needs two mobile phones, a PICAXE, and a balloon.

Merry Christmas,