Flicker parametrization interface

On small 8-bit microcontroller projects I often encounter the same problem – how to enter some run-time parameters into the microcontroller without implementing a complex user interface. For example, if I am building a motor driver I might want to parameterize the motor current, rotation direction, gain…

I could anticipate some jupers or dip-switches on the PCB, but this is rigid, limited and painful. Thus I tried to develop this simple ‘Flicker parameterization interface’ for 8-bit hobbyists.

The idea

The idea is to use your smartphone where you can adjust parameters using nice-looking GUI, and then send these parameters, using screen-flickering technique, into you microcontroller. The microcontroller uses a phototransistor (or photodiode) to receive data… You need:

  • a smartphone with the “Filcker” application
  • your GUI interface definition code (to be loaded into the Flicker application)
  • one phototransistor and one resistor
  • one input pin on your microcontroller
  • about 250 bytes of program memory inside your microcontroller

If you are interested to see a practical project that uses the Flicker interface you can visit this 1.5A stepper motor driver page.


Here is the simple schematic of the microcontroller interface:

The phototransistor can be either P or N type (I used the BPW40). The resistor is about 68kohm (you should experiment for best result). The resistor might not be needed if the microcontroller has internal pull-up resistor of appropriate value.

I think it might be good to put the phototransistor in some sort of opaque cylinder to prevent ambient light to reach it from side while you are programming. For example, you might just wrap it into black insulation tape leaving only its top protruding.

With some luck, the above circuit might provide some user feedback without spending an additional microcontroller pin. When the pin is programmed as input, parameterization is possible. When the pin is programmed as output signalization through LED is possible (for example: one long pulse when parameterization is successful; 5-10 short pulses when parameterization failed).

Communication protocol

I decided to use simplest, but not the fastest way to transmit data. The protocol is not practical to transmit more than 30 bytes (240 bits), and is intended to transmit less than 10 bytes (80 bits) of data. To transmit ‘1’, the smartphone will generate long light pulse, then short dark pulse. To transmit ‘0’, the smartphone will generate short light pulse, then long dark pulse. No exact timing is necessary.

The following diagram shows three bits (‘1-0-1’) being transmitted:

The following diagrams shows possible protocol implementations on transmitter and receiver sides.

Microcontroller programming

Here is a source code example showing how a receiving function can be implemented in a microcontroller:

unsigned char FlickerRead(unsigned char *buff,int bit_size)
 //we need 'dark' for at least 0.5 seconds to move to the next step
 unsigned char flicker_timer1=0;
 unsigned char flicker_timer2=0;
 while (flicker_timer1<12)
  if (!FLICKER_PIN) flicker_timer1=0;
  if (flicker_timer2>250) return 0; //error - timeout (no dark period)
  WaitLoop(40); //wait 40 milliseconds

 //now waiting for the start pulse - the first 'light' after dark period is the start pulse
 while (FLICKER_PIN)
  if (flicker_timer2>=40) {flicker_timer2=0;flicker_timer1++;}
  if (flicker_timer1>250) return 0; //error - timeout (no start pulse)
  WaitLoop(1); //wait 1 millisecond

 //start pulse arrived, we start recording
 unsigned char bit_cntr=0;
 while (bit_size)
  //timing the light pulse length
  while (flicker_timer1<250)
   if (FLICKER_PIN) break;
  if (flicker_timer1>=250) break; //finished (light pulse for 250ms)

  //timing the dark pulse length
  while (flicker_timer2<250)
   if (!FLICKER_PIN) break;
  if (flicker_timer2>=255) return 0; //error - dark pulse too long

  //storing the data
  if (flicker_timer1>=flicker_timer2) (*buff)|=0x80;
  if (bit_cntr==8) {bit_cntr=0;buff++;}
 return 1;

Of course, the code can be improved further.

The Flicker application for an Android smartphone

I made this simplest Android application (one reason for this project is because I wanted to learn some Android programming) where you can define your GUI interface and then send data to microcontroller. If someone will be interested, I might polish the application further, adding more features. However, I believe that any experienced smartphone programmer should be able to make such application in two days.You can download the android Flicker application (free, 68k, API level 15) from here.

To define your own GUI you need to enter some definition code into the application. The interface definition code follows simple rules:

Each line is a comma-separated list of values as follows: Number_of_bits, Description, Type, additional_parameters (depend on the type)

Here is one example of an interface definition code:

DEMO interface
8,Max current (x0.1A),EditInt,4
8,Gain factor,BarInt,15,0,50
1,Use damping filter,Checkbox,1
1,Reverse rotation,Checkbox,0
6,Fixed ID,FixedInt,37
8,ending checksum,Checksum

The ‘Number_of_bits’ determines how many bits will be transmitted from this GUI control element. The ‘Description’ is any text describing the GUI control (must not contain comma). If you leave the description empty or you name it "invisible", the field will not be displayed, but its data will be transmitted - useful for FixedInt fields.

At the moment, the ‘Type’ can be one of following few strings:

  • EditInt – creates an edit-box field where user can inter an integer (additional_parameters: default value)
  • BarInt – creates a slider that user can slide (additional_parameters: default value, minimum value, maximum value)
  • Checkbox – creates a checkbox that can be checked/unchecked by user (additional_parameters: default state)
  • FixedInt – displays the fixed, unchangeable integer (additional_parameters: value)
  • Chooser - creates a chooser (dropbox, spinner) to select from several options (additional_parameters: default choice index, list of choices separated by slash character). An example of chooser usage would be:
    2,Microstepping,Chooser,0,microsteps (8)/microsteps (4)/half-stepping
  • Checksum - is not displayed on the GUI, but a simple checksum of all previous bytes is transmitted during transmission.

Checksum computation details - checksum is modulo 256 sum of all bytes sent prior the checksum field. Take care that the checksum field starts at 8-bit-aligned location (only fully sent bytes are included into checksum computation)... In the "DEMO interface" example above following four bytes will be sent: 4, 15, 149, 168 (the first byte is the 'EditInt' field, the second byte is the 'BarInt' field, the third byte is combination of two checkboxes and a 'FixedInt' field [where the first bit is the state of the first checkbox '1', the second bit is the state of the second checkbox '0' and further 6 bits carry the number '37' from the 'FixedInt'], and the fourth byte is the checksum 168=4+15+149.

Because typing interface code directly into a smartphone is annoying, it is possible to put the code somewhere on the internet and access it by URL (into the code box you can type, for example, the following URL: http://gorupec.awardspace.us/iface.txt). At the moment there is no special support for the QR code readers.

As you can see many fancy GUI controls are not yet supported. Let me know if you are interested as it should not be a big problem for me to implement some improvements.


Of course, the communication is limited into one direction only (if I opted for sound communication I might have it bidirectional, but microcontroller programming would be considerably more complex).

The communication speed is also very limited (about 15 bits per second) because smartphone screen refresh rate is low (60Hz), because smartphone screen is inert and because the used communication protocol is suboptimal.

At the moment, the android application only sends bytes by transmitting least-significant-bit first. When sending fileds larger than 8-bit, lower byte will be transmitted first.

Danijel Gorupec, 2014