logo
  
Connecting a PICAXE OLED LCD to arduino
I recently bought this LCD from picaxe.com (AXE133Y). I was impressed by its quality and price and most importantly, I thought I could use it with my arduino projects by sacrificing only 1 pin.
 
 Unfortunately this was not possible straight out of the box!
 
It seems that the 18M2 Picaxe  chip prefers serial communication using inverted signals! The arduino uses normal signals so without modifying the firmware it is not possible for these devices to talk.
 
Modifying the code was straight forward but uploading it was simply a nightmare as I did not have the picaxe programming cable which looked exactly like my ftdi TTL-232 cable. There are 2 important differences:
 
1) The picaxe cable uses inverted signals whereas the FTDI cable uses non-inverted ones. The problem can be solved by using this program [use instructions here]

2) The wiring of the two cables is different
 
           [ ] Tip
           [ ] Ring
           |  |
           |  | Shield
          [   ]
Picaxe Cable
FTDI cable
Tip
Shield
Shield
Ring
Ring
Tip

Finally here is the code I used for the firmware (all credit to www.picaxe.com
 
; AXE133 Serial LCD/OLED using PICAXE-18M2; Emulates basic serial operation of the popular AXE033 module
; CPS, May 2011
; This is an open source firmware
; This code has been modified by 5B4WN
; December 9, 2011
; All credits to www.picaxe.com


; Supported Commands
; 0-7, 8-15    CGRAM characters
; 16-252    normal ASCII characters, according to selected character map table
; 253, X    display 16 character pre-saved message from EEPROM memory, X can be 0-15
; 254, X    LCD command, X can be 0 to 255
; 255, X    control outputs C.2, C.1, C.0 (via lower 3 bits of X)
;        So, if using a backlit LCD with the active low transistor driver
;        on output C.2, then 255,%000 switches backlight on and 255,%100 switches off

#picaxe 18M2

#define use_welcome    ; display the welcome message upon power up
#define use_OLED        ; enable this line for Winstar OLED modules

symbol line_length = 16    ; change to 20 for displays with 20 character lines

symbol baud = T4800_16    ; Serial baud rate 4800,N,8,1. Note main program //modified by 5B4WN runs at 16MHz

symbol spare0     = C.0 ; spare output 0
symbol spare1     = C.1 ; spare output 1
symbol spare2     = C.2 ; spare output 2 (or optional backlight)
symbol backlight     = C.2 ; optional backlight control for backlit LCDs, active low
symbol RX        = C.5    ; serial receive pin
symbol enable     = C.6    ; LCD enable
symbol rs         = C.7    ; LCD RS
; LCD data pins are on B.0 to B.7

; Store the 16 character user defined messages in EEPROM data memory
; First two messages are optionally used as welcome message

; If using a display with 20 characters you will need to edit
; the start addresses to be multiples of 20 (currently at 16)
; and add 4 characters to each message.
; Please remember 4 line displays always use the strange 1-3-2-4 layout.

;--#ifdef use_OLED       
EEPROM $00, ("  Serial OLED   ")     ; store msg in the EEPROM memory
;--#else
;--EEPROM $00, ("   Serial LCD   ")     ; store msg in the EEPROM memory
;--#endif
EEPROM $10, (" www.5b4wn.com ")     ; store msg in the EEPROM memory

EEPROM $20, ("This is msg 2   ")     ; store msg in the EEPROM memory
EEPROM $30, ("This is msg 3   ")     ; store msg in the EEPROM memory
EEPROM $40, ("This is msg 4   ")     ; store msg in the EEPROM memory
EEPROM $50, ("This is msg 5   ")     ; store msg in the EEPROM memory
EEPROM $60, ("This is msg 6   ")     ; store msg in the EEPROM memory
EEPROM $70, ("This is msg 7   ")     ; store msg in the EEPROM memory
EEPROM $80, ("This is msg 8   ")     ; store msg in the EEPROM memory
EEPROM $90, ("This is msg 9   ")     ; store msg in the EEPROM memory
EEPROM $A0, ("This is msg 10  ")     ; store msg in the EEPROM memory
EEPROM $B0, ("This is msg 11  ")     ; store msg in the EEPROM memory
EEPROM $C0, ("This is msg 12  ")     ; store msg in the EEPROM memory
EEPROM $D0, ("This is msg 13  ")     ; store msg in the EEPROM memory
EEPROM $E0, ("This is msg 14  ")     ; store msg in the EEPROM memory
EEPROM $F0, ("This is msg 15  ")     ; store msg in the EEPROM memory

;initialise LCD
init:
    gosub LCD_init         ; initialise LCD

; display welcome message if desired
;--#ifdef use_welcome   
    let b1 = 0            ; message 0 on top line
    gosub msg            ; do it

    low rs            ; command mode
    let pinsB = 192        ; move to line 2, instruction 192
    pulsout enable,1      ; pulse the enable pin to send data.
    high rs            ; character mode again
   
    let b1 = 1            ; message 1 on bottom line
    gosub msg            ; do it
;--#endif       
       
; main program loop, runs at 16MHz

main:

    serin RX,baud,b1            ; wait for the next byte

    ; NB keep character mode test as first item in this list to optimise speed
    if b1 < 253 then
        let pinsB = b1         ; output the data
        pulsout enable,1      ; pulse the enable pin to send data.
        goto main            ; quickly loop back to top
    else if b1 = 254 then
        low rs                  ; change to command mode for next character
        serin RX,baud,b1        ; wait for the command byte
        let pinsB = b1         ; output the data
        pulsout enable,1      ; pulse the enable pin to send data.
        high rs            ; back to character mode
        goto main            ; quickly loop back to top
    else if b1 = 253 then
        serin RX,baud,b1        ; wait for the next byte
        gosub msg            ; do the 16 character message
        goto main            ; back to top
    else ; must be 255
        serin RX,baud,b1        ; wait for the next byte
        let pinsC = b1 & %00000111 | %10000000
                        ; output the data on C.0 to C.1, keep RS high
        goto main            ; back to top
    end if


; power on LCD initialisation sub routine
LCD_init:
    let dirsC = %11000111    ; PortC 0,1,2,6,7 all outputs
    let dirsB = %11111111    ; PortB all outputs
   
   
   
;--#ifdef use_OLED
    ; Winstar OLED Module Initialisation
    ; according to WS0010 datasheet (8 bit mode)

    pause 500             ; Power stabilistation = 500ms

    ; Function set - select only one of these 4 character table modes
    ;let pinsB = %00111000     ; 8 bit, 2 line, 5x8 , English_Japanese table
    let pinsB = %00111001     ; 8 bit, 2 line, 5x8 , Western_European table1
    ;let pinsB = %00111010     ; 8 bit, 2 line, 5x8 , English_Russian  table
    ;let pinsB = %00111011     ; 8 bit, 2 line, 5x8 , Western_European table2
   
    pulsout enable,1      ;
       
    let pinsB = %00001100    ; Display on, no cursor, no blink
    pulsout enable,1    

    let pinsB = %00000001     ; Display Clear
    pulsout enable,1
    pause 7            ; Allow 6.2ms to clear display

    setfreq m16            ; now change to 16Mhz

    let pinsB = %00000010     ; Return Home
    pulsout enable,1

    let pinsB = %00000110     ; Entry Mode, ID=1, SH=0
    pulsout enable, 1



   
    high rs            ; Leave in character mode
    return


; display message from EEPROM sub routine
; message number 0-15 must be in b1 when called
; uses (alters) b1, b2, b3, b4
msg:
    let b2 = b1 & %00001111 * line_length
                        ; EEPROM start address is 0 to 15 multiplied by 16
    let b3 = b2 + line_length - 1 ; end address is start address + (line_length - 1)
    for b4 = b2 to b3            ; for 16 times
        read b4,b1            ; read next character from EEPROM data memory into b1
        let pinsB = b1         ; output the data
        pulsout enable,1      ; pulse the enable pin to send data.
    next b4                ; next loop
    return
   
 


To talk from arduino you can send the following commands
 
  • Clear screen as per manual is 254 followed by 1:
    • Serial.begin(4800);
    • Serial.write(254);
    • delay(10);
    • Serial.write(1);
    • Serial.print("hello World");
    • delay(10);

etc etc
 
 

A morse decoder for arduino
An algorithm for decoding Morse code with arduino, some inspiration from this article
 
From wikipedia:
The perfect morse code needs:
  1. short mark, dot or 'dit' (·) — 'dot duration' is one unit long
  2. longer mark, dash or 'dah' (–) — three units long
  3. inter-element gap between the dots and dashes within a character — one dot duration or one unit long
  4. short gap (between letters) — three units long
  5. medium gap (between words) — seven units long

The real morse code has a dot:dash ratio of 2.5:1 to 3.5:1

Firstly, we need to determine this ratio:
If the inter-element gap length is denoted as Tm and dot as Td:
Use the first ten time lengths to calculate Tm and Td
 
High Level Time=H_TIME [ie not pressing]
Low Level Time=L_TIME [ie key pressing]
blank a dot/dash array
R=H_TIME[n]/Tm
If (R with 0.5 and 1.5) {
      S=L_TIME[n-1]/Td
      if (S within 2.5 and 3.5) {
             dash
      } else {
             dot
      }  
advance to next element in dot/dash array


} else  if R (within 2.5-3.5) {
           we have a letter space hence decode array
}
 
 
Another algorithm obtained from here can be summarised in this diagram

 
 

Controlling the MCP4231 Digital Pot with the arduino
Using the datasheet here is how to control the MCP4231
 
129 steps (0-128)
10K

For arduino Mega:
use
int ss1 = 53;
int clk = 52;
int mosi = 51; 
 
 
//controlling MCP4231  10K
// 1-CS               14-+5V
// 2-SCK              13-NC
// 3-SI               12-+5V
// 4-GND              11-+5V
// 5- POT0 A          10-POT1 A
// 6- POT0 Wiper       9-POT1 Wiper
// 7- POT0 B           8-POT1 B

int ss1 = 2;
int clk = 4;
int mosi = 3;
int ledPin=13;

// Variables and bytes
byte pot0 = B00010000; // write to pot 0  pins 5 and 6
byte pot1 = 0x0; // write to pot 1 pins 9 and 10

byte nil=0;

int resistance;
String serialCommand;

void setup()
{
  Serial.begin( 9600 );

  pinMode( ss1, OUTPUT );
  pinMode( clk, OUTPUT );
  pinMode( mosi, OUTPUT );

  pinMode( ledPin, OUTPUT );

  digitalWrite( ss1, HIGH );
  digitalWrite( clk, HIGH );

  Serial.println( "Ready. value; eg OHM:1000; =1K Ohm" );
  writeValue(pot1, 0);
}

void loop()
{
  if (Serial.available()>0) {

    byte buf=Serial.read();
    serialCommand +=String(buf);

    if (serialCommand.length()>20) {
      serialCommand=""; //avoid too long strings
    }

    if (buf==59) {

      //; received
      if (serialCommand.startsWith("OHM:")) {
        int n;
        char carray[6];
        String newstep=serialCommand.substring(serialCommand.indexOf(":")+1, serialCommand.length()-1);  
        newstep.toCharArray(carray, sizeof(carray));
        resistance = atoi(carray);
        if (resistance<10001) {
          n=map(resistance,0,10000,0,128);

          writeValue(pot0, n);
          Serial.println(resistance);
          Serial.println(n);
        }

      }
      serialCommand="";
    }
  }
}




void writeValue(int pot, int value) {
  digitalWrite( ss1, LOW );
  spi_transfer(pot);
  spi_transfer(value);
  digitalWrite( ss1, HIGH );

}





void spi_transfer( byte data )
{
  int i;

  digitalWrite( clk, LOW );

  for( i=1; i<=8; ++i )
  {
    if( data > 127 ) {
      digitalWrite( mosi, HIGH );
    }
    else {
      digitalWrite( mosi, LOW );
    }

    digitalWrite( clk, HIGH );
    data = data << 1;
    digitalWrite( clk, LOW );
  }
}

 
 
 
 

SO2RDuino - A USB SO2R Box by K1XM
K1XM has just published details of how to build an SO2R box using the arduino platform in NCJ.
 
Some of the features are:
  • switches headphones, microphone, CW keyer and PTT (from the computer or a footswitch)
  • uses relays for headphone and microphone switching
  • communicates through, and is powered by, a USB port
  • includes override switches for transmit and receive and LEDs to display status
  • incorporates a BLEND control that blends left and right channels in stereo mode
  • provides four-bit outputs, with band information for each radio. The outputs are compatible with Array Solutions, Top-Ten, Unified Microsystems or similar band decoders.
  • includes a "latch" mode. If the computer transmits (i.e., sets PTT), the headphones will be connected in mono to the non-transmitting radio, reverting to normal operation when the radio stops transmitting.
  • can be set so it will not go into stereo - useful for people who have a hearing issue in one ear.
  • is compatible with N1MM Logger, WriteLog, Win-Test and similar logging programs

  • The full article can be found here

    A YAESU band decoder converter for use with ICOM rigs
    Icom rigs have their own unique way of providing  information to external rigs based on the current band. This information is provided on a single pin on the ACC-2 socket by varying the voltage from 0-8V (see figure below).
     
     
     
     
    Most peripheral equipment use the ubiquitous YAESU band data method as follows
     
     
    This project uses an arduino to read the voltage from the ACC2 pin, determines the band and then converts it to a YAESU band data to use with the many peripherals that support the latter. Read more here.