Thursday, September 20, 2012

Arduino as Serial LCD Display


Project Objective: In this project we will use the Arduino to emulate the PH Anderson #117 serial text display minus big numbers. The layout of a piggyback pcb will complete the  project.

Introduction: See the discussion in the "Controlling a Serial Display" project which covers several of the serial LCD displays on the market. Most of these products have a similar command set and the sketch presented here could be modified to emulate many of these.

Serial LCD displays are available in both text and graphic versions. This project covers text displays with one to four lines and up to 40 columns. Initially, the displays will be limited to 80 total characters, a limitation of the Arduino standard LCD library.

Since the serial LCD is a one wire device, all control of the LCD terminal must use command sequences. Here are the commands used in this project:


Arduino Serial LCD Rev. A: Command Set (as of 9/16/12)
Command 
?a home cursor
?b destructive backspace
?c# set cursor style,   0= none 2= blinking 3=underline
?f clear screen
?g Beep 
?h Backup Cursor (Non-destructive backspace)
?i Forward cursor
?j Up cursor
?k Down cursor
?l Clear cursor line
?m Carriage Return
?n CRLF, cursor at start of next line, line cleared
?p### Position cursor x = ##, y = #
?x##  Position cursor on x column, (two characters are required), first column is column 0, 
?y# Position cursor at y row, first row is row 0 (one character only)
?? display a "?"
?! Send direct command to LCD
?B Backlight Intensity – sets PWM value, two hex digits req. (00 to FF)
?D#      Define custom character. See text.
?# Print a custom character
?H High output on auxiliary digital pins: valid numbers are 1,2,3,4
?L Low output on auxiliary digital pins: valid numbers are 1,2,3,4
?G Configure for LCD geometry. Supported formats: 2X16, 2X20, 2X24, 2X40, 4X16 and 4X20.


Except for the ?p### command they are identical to the PH Anderson, #117 chip. The start character for a command sequence is a '?', but this can be easily changed in the sketch, say to a '!'. The sketch below compiles, but some commands are missing.

One of the nice features of the #117 command set is that control can be accomplished using a PC termial program. In fact, using the Arduino IDE to update the code the built in terminal can be opened to test changes.The piggyback pcb can be modified and updated the same way.

Note: As of 10/08/12 the code was updated, as well as the schematic.The schematic changes were made to simplify the piggyback pcb layout. Because of this there were also changes to code. Several additional commands have been added and we will continue to add more.


Schematic Used with Solderless Breadboard:



The schematic above shows the parts which need to be added to the solderless breadboard for this project. The headers in the schematic are the the headers on the Arduino board. The piggyback board will require a different schematic and include the atmega328, as well as, serial interface circuits and jumpers.

The image below shows the Arduino Serial LCD connected to an Arduino sending serial data at 9600 baude. The text being sent is "Temperature" and "76.8" or "77.6", where the word Temperature is sent once and the numbers sent alternately in the loop section of the sketch. Before the numbers are sent the cursor is positioned at character column 14. The small round object is a piezo speaker.


Arduino on left is sending serial data to Arduino on right.
















Sketch:Version  0.6


/*
Arduino_PHAnderson #117 Serial LCD emulator
Date: 10/08/12
Author: R. LaSalle

*/

#include <LiquidCrystal.h>
#include <EEPROM.h>

/* LCD pin assignments
RS 8
RW 9
E  10
D4 4
D5 5
D6 6
D7 7
*/

#define BP 3
#define BL 11
#define Bd0 14
#define Bd1 15

#define maxrowloc 0
#define maxcolloc 1
#define bootscrloc 2
#define curtypeloc 3
#define ledblloc 4
#define tabloc 5
#define user0 10
#define user1 30
#define user2 50
#define user3 70

#define commchr '?'
//#define VER .5

uint16_t bauderate = 9600;
uint8_t maxrow = 4;
uint8_t maxcol = 20;
uint8_t bootscr = 1;
uint8_t ledbl = 0x7f;
uint8_t nrow =0;
uint8_t ncol =0;
int8_t temp =0;
int8_t temp1 =0;
int8_t temp2 =0;
int8_t temp3 =0;

LiquidCrystal lcd(8,9,10,4,5,6,7);

void setup() {
//  EEPROM.write(maxrowloc,0);
//  EEPROM.write(maxcolloc,0);
  temp=EEPROM.read(maxrowloc);
  temp1=EEPROM.read(maxcolloc);
  if(temp==0 && temp1==0){  //Is EEPROM empty? If yes load defaults.
    maxrow=4;
    maxcol=20;
    EEPROM.write(maxrowloc,maxrow);
    EEPROM.write(maxcolloc,maxcol);
  }
  maxrow=EEPROM.read(maxrowloc);
  maxcol=EEPROM.read(maxcolloc);
  lcd.begin(maxcol,maxrow); // Change this for other screen sizes.
  pinMode(Bd0,INPUT);  //bauderate set bit 0
  pinMode(Bd1,INPUT);  //bauderate set bit 1
  digitalWrite(Bd0,HIGH);  //pullup
  digitalWrite(Bd1,HIGH);  //pullup
  if(digitalRead(Bd0)==LOW && digitalRead(Bd1)==LOW){bauderate=2400;}
  if(digitalRead(Bd0)==HIGH && digitalRead(Bd1)==LOW){bauderate=9600;}
  if(digitalRead(Bd0)==LOW && digitalRead(Bd1)==HIGH){bauderate=19200;}
  if(digitalRead(Bd0)==HIGH && digitalRead(Bd1)==HIGH){bauderate=38400;}
  Serial.begin(bauderate); // Default baudrate.
  pinMode(BL,OUTPUT);
  pinMode(BP,OUTPUT);

  analogWrite(BL, ledbl); // Set maximum brightness.

// Boot Screens
  if(bootscr==1){    //Config screen
    ncol=0;
    nrow=0;
    lcd.setCursor(ncol,nrow);  //home cursor
    lcd.print("Arduino_PHA117");
    lcd.setCursor(0, 1);
    lcd.print("G:");lcd.print(maxrow);lcd.print("x");
    lcd.print(maxcol/10);lcd.print(maxcol%10);
    lcd.print(" B:");lcd.print(bauderate);
    lcd.setCursor(0,0);  //home cursor
  }
}

void loop() {
  byte rxbyte = getc(); // Command
//byte temp; // Parameter

  if (rxbyte == commchr) {
    switch (getc()) {
    case 'p': // Set cursor position (2 parameters, column, row)
 temp=getn();
 temp1=getn();
          temp2=getn();
          if(temp=='e'||temp1=='e'){
            error();
            break;
          }
          temp=temp*10+temp1;
          if(temp>maxcol-1){
            error();
   break;
 }
          ncol=temp;
            if(temp2=='e'){
             error();
            break;
           }
           if(temp2>maxrow-1){
             error();
            break;
           }
            nrow=temp2;                
      lcd.setCursor(ncol, nrow);
      break;
    case 'a': // Cursor home (doesn't clear the screen!)
      lcd.home();
      ncol=0;
      nrow=0;
      break;
case 'b': //Destructive backspace
 lcd.command(16);  //cursor back
 lcd.write(' ');    // write space
 lcd.command(16);  //cursor back
 ncol=ncol-1;
 break;
    case 'c': // Set Cursor type
      switch (getc()){
        case '0':
          lcd.noCursor();
          lcd.noBlink();
          break;
        case '2':
           lcd.cursor();
           lcd.noBlink();
           break;
        case '3':
            lcd.cursor();
            lcd.blink();
            break;
           default:
           break;
        }
        break;
    case 'f': // Clear screen
      lcd.clear();
      ncol=0;
      nrow=0;
      break;
    case 'g': //beep
      tone(BP,4000,250);
      break;
    case 'h': // Move cursor back
      if(ncol>0){
lcd.command(16);
ncol=ncol-1;
      }
      break;
    case 'i': // Move cursor forward
if(ncol<maxcol){
lcd.command(20);
 ncol=ncol+1;
}
      break;
    case 'j': //Cursor up
if(nrow>0){
 nrow=nrow-1;
 lcd.setCursor(ncol,nrow);
}
     break;
     case 'k': //Cursor down
if(nrow<maxrow){
 nrow=nrow+1;
 lcd.setCursor(ncol,nrow);
}
      break;
      case 'l':  //clear cursor line
        ncol=0;
 //       maxcol=20;
        lcd.setCursor(ncol,nrow);
        for(byte i=0;i<=maxcol-1;i++){lcd.write(' ');}
        ncol=0;
        lcd.setCursor(ncol,nrow);
      break;
      case 'm':  //CR
        ncol=0;
        lcd.setCursor(ncol,nrow);
      break;
      case 'n':  //CRLF
        ncol=0;
        if(nrow<maxrow-1){nrow=nrow+1;}
        lcd.setCursor(ncol,nrow);
      break;
      case 'x':
          temp=getn();
          temp1=getn();
          if(temp=='e'||temp1=='e'){
            error();
            break;
          }
          temp=temp*10+temp1;
          if(temp>maxcol-1){
            error();
   break;
 }
          ncol=temp;
          lcd.setCursor(ncol,nrow);
break;

case 'y':
          temp=getn();
           if(temp=='e'){
             error();
            break;
           }
           if(temp>maxrow-1){
             error();
            break;
           }
            nrow=temp;
            lcd.setCursor(ncol,nrow);
        break;
       case 'B':
         temp=geth();
         temp1=geth();
         if(temp==0xff || temp1==0xff){break;}
         temp=temp<<4;
         ledbl=temp+temp1;
         EEPROM.write(ledblloc,ledbl);
         analogWrite(BL,ledbl);
       break;
       case 'G':  //enter R,C
         temp=getn();
         temp1=getn();
         temp2=getn();
         if(temp=='e' || temp1=='e' || temp2=='e'){error();break;}
         maxcol=temp1*10+temp2;
         maxrow=temp;
         EEPROM.write(maxcolloc,maxcol);
         EEPROM.write(maxrowloc,maxrow);
       break;
    }
  }
  else{
  // Otherwise its a plain char so we print it to the LCD.
  lcd.write(rxbyte);
  ncol=ncol+1;
  }
}

/*
 * Waits for a byte to be available, reads and returns it.
 */
byte getc() {  //get character
  while (Serial.available() == 0);
  return Serial.read();
}

byte getn() {  //get decimal digit
  byte temp;
  while (Serial.available() ==0);
  temp=Serial.read()-48;
  if(0>temp>9){
    return 'e';
  }
  else{
  return temp;
  }
}

byte geth(){  //get hex digit
  byte temp=getc();
  if(temp>=0x30 && temp<=0x39){
    temp=temp-0x30;
    return temp;
  }
  if(temp>=0x61 && temp<=0x66){
    temp=temp-0x57;
    return temp;
  }
  return 0xff;
}

void error(){
  tone(6,4000,250);
  return;
}



.

To Be Continued

Tuesday, July 3, 2012

uLab40AVR, the ATmega1284P for Solderless Breadboard

Project Objective: The uLab40AVR is designed to be functional similar to the uLab28AVR.

Introduction: This PCB is designed to be a mate to the Daiduino except that it uses the Sanguino pin designations. This will not cause a problem because of the Arduino IDE pin maping. For example, if you connect a LED/resistor to D13 on the uLab40AVR and the Daiduino, then select the appropriate board in the Arduino IDE, the blink sketch will work.

Specifications:

  1. Use of thru hole parts except for regulators
  2. Dual regulators for 5V and 3.3V
  3. Use a breakout boards for serial communication, USB or RS232
  4. Power switch
  5. Use jumpers for selecting power source.
  6. 36 pin header for signals and two separate pin sets for powering the SLBB.




Note: The design is not complete. 7/3/12

uLab28AVR, Arduino for Solderless Breadboard

Project Objective: To transpose the Arduino to a solderless breadboard plugin.

Introduction: This board has all the features of the GMduino, Arduino clone, shown on another post. The digital and analog pin designations are identical to the GMduino and, therefore, the Duemilanove. In addition, the ATmega328P pin designations are also shown.

Specifications:
  1. Use of thru hole parts except for regulators
  2. Dual regulators for 5V and 3.3V
  3. Use a breakout boards for serial communication, USB or RS232
  4. Power switch
  5. Use jumpers for selecting power source.
  6. 25 pin header for signals and two separate pin sets for powering the SLBB.




GMduino, a Buildable Clone

Project Objective: Design a Arduino clone that is easy to assemble for clubs and beginners

Introduction: With the criteria of ease of assembly, the first problem is the FTDI USB chip which even for the experienced assembler is not an easy mounting task, but the availability of small FTDI breakout boards solves the problem. I am using the BUB II by Modern Devices since they leave the connector for you to assemble which I add underneath the board.. Adafruit has the Friend, but it is pre-assembled with the connector on the top.

The standard 7805 type regulator is real-estate hungry and two will be needed, so surface mount LDO regulators are used. These are three pin devices and mounting is not difficult. Low drop out, LDO, devices are used to limit heat dissipation. In fact, we use a 6V wall power supply which at low current has a 8.5VDC output where a 9V wart is at 12VDC.

The commercial Arduino uses a circuit for switching between external power, wart, and USB which can take up surface space unless smd parts are used. Further, it would be nice if RS232 serial communiction could also be used which means the clone would need to supply power to that breakout. So we opted for jumpers for both power selection and board voltage. In addition a power switch was added for convenience during development and if not wanted can be jumpered out.

Finally, a vertical reset switch is placed at the front of the board as well as the LED's. This means that with a shield mounted on the Arduino the reset button is still accessible and the LED's can be seen.

Specifications:
  1. Use of thru hole parts except for regulators
  2. Dual regulators for 5V and 3.3V
  3. Use a breakout board for serial communiction
  4. Place LED's and reset switch at front of board
  5. Add power switch
  6. Use jumpers for selecting power source.

GMduino with BUB II. Note the mounting position of BUB II connector.






Friday, June 22, 2012

GMduino II, Arduino Clone with RTC and EEPROM

Project Objective: To design an Arduino clone with through hole parts for easy assembly. The clone also includes an on board real time calendar clock with battery backup and an EEPROM. The board should operate at 5V and 3.3V including the RTC.

Specifications:
  1. Arduino clone with stacking connectors
  2. MCU: ATmega328P with Optiboot
  3. Through hole parts, except for regulators
  4. Serial communication using breakout boards
  5. Dual ldo regulators for 5V and 3.3V
  6. Power :input:  6V to 9V wart or USB jumper selectable
  7. Power switch
  8. Auto reset defeat switch
  9. On board I2C, EEPROM and RTC with battery backup.
  10. Vertical reset and ISP at front
Introduction: The project is an outgrowth of the Rainwater Monitoring System , RMS. The original development was done with the uLab28 PIC, then resulting in the Picduino. The RMS is basically a water tank level data logger with LCD display and keyboard.






Note: Layout complete ready for BatchPCB, GMduino.03C

Under construction

Thursday, June 14, 2012

Daiduino, an Arduino form with the ATmega1284P

Project Objective:
Wouldn't you like to have an Arduino that had 4 times the code capacity, more IO pins and used standard shields, but was only slightly larger? So would I. Further, I would like it to use through hole parts, so that it could be assembled as a kit. By the way, dai is a japanese word that means great or big. So Daiduino is a big Arduino but not a mega Arduino.

Discussion:
I started my Google search, looking at the Sanguino which uses the ATmega644P and has 64k bytes of code space, but soon found the ATmega1284P which has the same pinouts and 128k code space. As a matter of fact the Atmega1284P can be used on the Sanguino pcb. Another interesting item is that there is only 6 cent difference in price. Update: Downloading the Sanguino ZIP file indicated that the ATmega1284P is also included in their design.

Maniacbug site has the most useful data for this project and, in particular, have integrated the ATmega1284P into the Arduino IDE 1.0 environment. So the next step is to determine board size and pin assignments. Since I have already designed a through hole Arduino clone, transfering the power section to the Daiduino will be the first step. That process created a board 3.4" by 2.1".

For pin assignments, there are two designs on the Web to look at, Calunium and Bobuino.. Of the two the Calunium can use a standard shield, but is only USB powered. There is limited information on the Bobuino, but Maniacbug includes it in his zip file.

Specifications:
  1. Same width as the Arduino but longer, 2.1" by 3.5"
  2. Basic set of stacking connectors, UNO
  3. Dual regulators for 3.3V and 5V
  4. Power source: USB or wart
  5. USB interface on a plug in, such as a BUB II
  6. Through hole parts with the exception of the regulators.
  7. LED's, reset switch and ISP at front of the board
  8. Jumpers A4, A5 to I2C for UNO compatibility
  9. Jumper Auto Reset
Note: First version PCB ready for Batchpcb, 06/18/12. Ordered 06/19/12

Working

Friday, May 18, 2012

Bootloaders: How they Work.

Micro controller units are devices which contain a processing unit, programming and data memory and I/O. Early MCU's could not modify its program memory only the data memory. The program memory of present day MCU's can be modified with an in circuit programmer - ISP or ICSP - thru designated pins on the device or by the processor using special instructions.

A bootloader  is firmware, usually written into upper memory, which is executed when the MCU is reset. Typically, on reset, the bootloader waits for data to be input on the serial port and if this does not happen in a few seconds the bootloader jumps to the previously loaded code. If the data does start flowing, it is checked for correct protocol and loaded into program memory. The Atmel ATmega and the Microchip 18F MCU's handle bootloaders in a similar way.

A bootloader PC application interfaces with the MCU using the serial port. Before using the pc app to download the hex code, the reset switch at the MCU must be pressed. This sequence can be simplified by the PC application first triggering the serial port's DTR signal which at the MCU is connected to the reset pin. On the Arduino this is called auto reset.