i am a beginner to microcontroller and I just got into ADC but whenever I try to do a conversion it never works, I am trying to display the result on an LCD but the problem is not the LCD's because I tried its code alone and it worked so the problem is definitely the ADC's registers, here is the full code::
main.c:
#include "config.h"
int result;
void main(){
TRISAbits.TRISA0 = 1; //Set Port A for input
ADCON0 = 0b01000000; //Configuring ADCON0 register
ADCON1 = 0b10000000; //Configuring ADCON1 register
ADCON0bits.ADON = 1; //Turn on ADON bit in ADCON0 register to turn on ADC module
__delay_us(50); //Delay for the capacitor to be charged
ADCON0bits.GO_DONE = 1;
while(ADCON0bits.GO_DONE == 1);
result = ADRESH && ADRESL;
initLCD();
write_character(result);
while(1);
}
config.h:
#include <xc.h>
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
// CONFIG
#pragma config FOSC = XT // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = ON // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#define _XTAL_FREQ 4000000
void send_command(int command);
void write_character(int character);
void enable_blink(void);
void moveto(char b6, char b5, char b4, char b3, char b2, char b1, char b0);
void initLCD(void);
void send_command(int command){
PORTCbits.RC0 = 0;
PORTB = command;
enable_blink();
}
void write_character(int character){
PORTCbits.RC0 = 1;
PORTB = character;
enable_blink();
}
void enable_blink(){
PORTCbits.RC1 = 1;
__delay_ms(10);
PORTCbits.RC1 = 0;
__delay_ms(10);
}
void moveto(char b6, char b5, char b4, char b3, char b2, char b1, char b0){
PORTCbits.RC0 = 0;
PORTBbits.RB7 = 1;
PORTBbits.RB6 = b6;
PORTBbits.RB5 = b5;
PORTBbits.RB4 = b4;
PORTBbits.RB3 = b3;
PORTBbits.RB2 = b2;
PORTBbits.RB1 = b1;
PORTBbits.RB0 = b0;
enable_blink();
}
void initLCD(){
TRISB = 0;
TRISC = 0;
send_command(0x38);
__delay_us(40);
send_command(0x01);
__delay_ms(1.75);
send_command(0x0C);
__delay_us(40);
}
You may have a problem with your result line. Try the following:
result = ( ( ADRESH << 8 ) | ( ADRESL ) )
The double & operator ( && ) is the logical AND. AND will return true ( 1 ) as long as ADRESH and ADRESL are both greater than 1. You want the bitwise OR ( | ) operator to combine two bytes into one int, with the ADRESH as the most-significant-byte and the ADRESL as the least-significant-byte.
Hopefully this works!
Related
I'm working with a PIC16F628A but the IDE won't accept the _delay_ms command and doesn't build/compile, I don't know what to do... here is my code:
#include <xc.h> // STANDARD INCLUDE FILE FOR MICROCHIP PRODUCTS
// uc CONFIG (START)
#pragma config FOSC = HS // 4MHz EXTERNAL CLOCK
#pragma config WTDE = ON
#pragma config PWRTE = OFF
#pragma config MCLRE = ON
#pragma config BOREN = ON
#pragma config LVP = ON
#pragma config CPD = OFF
#pragma config CP = OFF
// uC CONFIG (END)
#define _XTAL_FREQ 4000000
#define BT1 PORTA.RA0 // Button with number 1
#define BT2 PORTA.RA1 // Button with number 2
#define BT3 PORTA.RA2 // Button with number 3
#define BT4 PORTA.RA3 // Button with number 4
#define a PORTB.RB0 // "a" segment from 7-segment display
#define b PORTB.RB1 // "b" segment from 7-segment display
#define c PORTB.RB2 // "c" segment from 7-segment display
#define d PORTB.RB3 // "d" segment from 7-segment display
#define e PORTB.RB4 // "e" segment from 7-segment display
#define f PORTB.RB5 // "f" segment from 7-segment display
#define g PORTB.RB6 // "g" segment from 7-segment display
void main ()
{
TRISA = 0x01;
TRISB = 0x00;
PORTA = 0x00;
PORTB = 0x00;
while(1)
{
if (BT1 == 1)
{
a = 0x00;
b = 0x01;
c = 0x01;
d = 0x00;
e = 0x00;
f = 0x00;
g = 0x00;
_delay_ms(5000);
a = 0x00;
b = 0x00;
c = 0x00;
d = 0x00;
e = 0x00;
f = 0x00;
g = 0x00;
_delay_ms(1000);
}
}
}
Do I need to add libraries? This code worked fine in MikroC but I'm trying to learn MPLAB since it's free and seems to be an industry standard tool for embedded systems.
You don't need an extra library, but in xc8 the name of the function is__delay_ms(...) with two _.
Please remember, these functions are actually in line macros and they have maximum delay values that depend on part type and clock frequency. To get longer delays using these macros put them in a for loop. I guess __delay_ms(5000) is a little bit to much.
Using a PIC18F47J53, MPLAB x, XC8 (v2.31), I am trying to use the internal RTCC, but I cannot see it counting (the seconds). The register RTCVALL, is not changing after waiting a few seconds.
I would like to use the 8MHz internal oscillator for the main clock, and the internal INTRC for the RTCC. Maybe first someone can confirm is it possible to use those 2?
The code is fairly simple, just setting a "seconds" value in RTCVALL, wait a bit, read the same register and hoping to find it has changed.. but it hasn't.
I am posting the main part of the code.
Other question, what is the RTCC pin is supposed to output? I have chosen the "seconds" as output, but if it is supposed to toggle high/low every seconds, where can I see in the datasheet the duty cycle? in my case the LED on RTCC pin stays solid high.
'''
// CONFIG1L
#pragma config WDTEN = OFF // Watchdog Timer (Disabled - Controlled by SWDTEN bit)
#pragma config PLLDIV = 1 // PLL Prescaler Selection (No prescale (4 MHz oscillator input drives PLL directly))
#pragma config CFGPLLEN = OFF // PLL Enable Configuration Bit (PLL Disabled)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset (Enabled)
#pragma config XINST = OFF // Extended Instruction Set (Disabled)
// CONFIG1H
#pragma config CPUDIV = OSC1 // CPU System Clock Postscaler (No CPU system clock divide)
#pragma config CP0 = OFF // Code Protect (Program memory is not code-protected)
// CONFIG2L
#pragma config OSC = INTOSC // Oscillator (INTOSC)
#pragma config SOSCSEL = HIGH // T1OSC/SOSC Power Selection Bits (High Power T1OSC/SOSC circuit selected)
#pragma config CLKOEC = ON // EC Clock Out Enable Bit (CLKO output enabled on the RA6 pin)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor (Enabled)
#pragma config IESO = ON // Internal External Oscillator Switch Over Mode (Enabled)
// CONFIG2H
#pragma config WDTPS = 32768 // Watchdog Postscaler (1:32768)
// CONFIG3L
#pragma config DSWDTOSC = INTOSCREF// DSWDT Clock Select (DSWDT uses INTRC)
#pragma config RTCOSC = INTOSCREF // RTCC Clock Select (INTRC)
#pragma config DSBOREN = ON // Deep Sleep BOR (Enabled)
#pragma config DSWDTEN = ON // Deep Sleep Watchdog Timer (Enabled)
#pragma config DSWDTPS = G2 // Deep Sleep Watchdog Postscaler (1:2,147,483,648 (25.7 days))
// CONFIG3H
#pragma config IOL1WAY = ON // IOLOCK One-Way Set Enable bit (The IOLOCK bit (PPSCON<0>) can be set once)
#pragma config ADCSEL = BIT10 // ADC 10 or 12 Bit Select (10 - Bit ADC Enabled)
#pragma config MSSP7B_EN = MSK7 // MSSP address masking (7 Bit address masking mode)
// CONFIG4L
#pragma config WPFP = PAGE_127 // Write/Erase Protect Page Start/End Location (Write Protect Program Flash Page 127)
#pragma config WPCFG = OFF // Write/Erase Protect Configuration Region (Configuration Words page not erase/write-protected)
// CONFIG4H
#pragma config WPDIS = OFF // Write Protect Disable bit (WPFP<6:0>/WPEND region ignored)
#pragma config WPEND = PAGE_WPFP// Write/Erase Protect Region Select bit (valid when WPDIS = 0) (Pages WPFP<6:0> through Configuration Words erase/write protected)
#pragma config LS48MHZ = SYS48X8// Low Speed USB mode with 48 MHz system clock bit (System clock at 48 MHz USB CLKEN divide-by is set to 8)
#define UINT_TO_BCD_ONES(x) ((x) % 10)
#define UINT_TO_BCD_TENS(x) (((x) % 100) / 10)
#define BCD_TO_UINT_TENS(x) ((x) >> 4)
#define BCD_TO_UINT_ONES(x) ((x) & 0x0F)
void main(void)
{
// set to 8MHz internal oscillator
OSCCON = 0x70;
// not sure that is necessary but either 0 or 1 don't work
OSCTUNEbits.INTSRC = 1;
pic_uart1_init(UART_BDS_9600);
__delay_ms(1000);
uint8_t seconds = 0;
// seconds RTCC output pin
PADCFG1bits.RTSECSEL1 = 0;
PADCFG1bits.RTSECSEL0 = 1;
pic_rtc_set_alarm_output(ON);
pic_rtc_enable(ON);
pic_rtc_wr_enable(ON);
pic_rtc_set_seconds(45);
pic_rtc_wr_enable(OFF);
// wait some time
for (int i = 0; i < 12; i++){
__delay_ms(1000);
printf("-> RTCVALL = %d\n", RTCVALL);
printf("-> RTCVALH = %d\n", RTCVALH);
}
pic_rtc_read_seconds(&seconds);
pic_rtc_enable(OFF);
printf("seconds = %d\n", seconds);
}
pic_status_t pic_rtc_enable(feature_status_t set_status)
{
pic_rtc_wr_enable(ON);
RTCCFGbits.RTCEN = set_status;
pic_rtc_wr_enable(OFF);
return PIC_SUCCESS;
}
pic_status_t pic_rtc_set_alarm_output(feature_status_t set_status)
{
RTCCFGbits.RTCOE = set_status;
return PIC_SUCCESS;
}
pic_status_t pic_rtc_wr_enable(feature_status_t set_status)
{
INTCONbits.GIE = 0;
EECON2 = 0x55;
EECON2 = 0xAA;
RTCCFGbits.RTCWREN = set_status;
INTCONbits.GIE = 1;
return PIC_SUCCESS;
}
pic_status_t pic_rtc_read_seconds(uint8_t *seconds)
{
// point to minutes
RTCCFGbits.RTCPTR1 = 0;
RTCCFGbits.RTCPTR0 = 0;
printf("RTCCFGbits.RTCPTR1 = %d\n", RTCCFGbits.RTCPTR1);
printf("RTCCFGbits.RTCPTR0 = %d\n", RTCCFGbits.RTCPTR0);
printf("RTCCFGbits.RTCWREN = %d\n", RTCCFGbits.RTCWREN);
uint8_t buffer_rd_sec = RTCVALL;
printf("buffer_rd_sec (BCD) = 0x%02x\n", buffer_rd_sec);
*seconds = (uint8_t)((BCD_TO_UINT_TENS(buffer_rd_sec) * 10) + (BCD_TO_UINT_ONES(buffer_rd_sec)));
return PIC_SUCCESS;
}
pic_status_t pic_rtc_set_seconds(uint8_t seconds)
{
if (seconds > 59)
return PIC_FAIL;
// point to seconds
RTCCFGbits.RTCPTR1 = 0;
RTCCFGbits.RTCPTR0 = 0;
printf("RTCCFGbits.RTCPTR1 = %d\n", RTCCFGbits.RTCPTR1);
printf("RTCCFGbits.RTCPTR0 = %d\n", RTCCFGbits.RTCPTR0);
printf("RTCCFGbits.RTCWREN = %d\n", RTCCFGbits.RTCWREN);
uint8_t buf_ones = UINT_TO_BCD_ONES(seconds);
printf("buf_ones = 0x%02x\n", buf_ones);
uint8_t buf_tens = UINT_TO_BCD_TENS(seconds);
printf("buf_tens = 0x%02x\n", buf_tens);
uint8_t buffer = buf_tens << 4 | buf_ones;
printf("buffer = 0x%02x\n", buffer);
RTCVALL = buffer;
return PIC_SUCCESS;
}
'''
Thanks for having a look and help
I got it working, looks like it wasn't the understanding of the PIC the problem, but the XC8 compiler instead..
I thought the RTCWREN bit had to be checked before enable the RTCEN
pic_status_t pic_rtc_enable(feature_status_t set_status)
{
while(!RTCCFGbits.RTCWREN); // wait for the bit to be set
RTCCFGbits.RTCEN = set_status;
return PIC_SUCCESS;
}
and found that the bit wasn't set at all, resulting the rest of the code been ignored.
so I looked into my pic_rtc_wr_enable function and I am very puzzled why the parameter set_status is making the block!
it is an enum,
typedef enum {
OFF = 0,
ON = 1,
} feature_status_t;
but if you replace the code with
pic_status_t pic_rtc_wr_enable(feature_status_t set_status)
{
if (set_status == 1) {
INTCONbits.GIE = 0;
EECON2 = 0x55;
EECON2 = 0xAA;
RTCCFGbits.RTCWREN = 1;
INTCONbits.GIE = 1;
}
return PIC_SUCCESS;
}
then it works perfectly fine.
So why XC8 doesn't substitute my enum ON with its int value of 1 for the bit assignment? despite it works in the check?
Any ideas?
For the RTCC pin, got it working too now, and it looks like the pin out is pulsing every seconds (in my case), and duty cycle is 50%.
I'm using PIC10F322 and timer0 with interrupt, trying to blink an LED, on for 1s and then off for another 1s. I had tried coded the timer called for interrupt, and it work good. But the counting for time isn't correct. The counting was On for about 2s and then Off for another 2s, which is isn't correct. I wonder is there something wrong with the calculation? The chip is 16MHZ, timer0 is 8 bits and set prescaler to 256. My attempt is to trigger interrupt every 1ms, then do a 999 loop count to hit 1 second.
My calculation is:
256 - [(Delay * Fosc) / (prescaler*4)] = 256 - [(1ms * 16000000)/(256*4)] = 240
#define _XTAL_FREQ 16000000
#include <xc.h>
#pragma config FOSC = INTOSC // Oscillator Selection bits (INTOSC oscillator: CLKIN function disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF // MCLR Pin Function Select bit (MCLR pin function is MCLR)
#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)
#pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
#pragma config LPBOR = ON // Brown-out Reset Selection bits (BOR disabled)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
int z = 0,count=0;
void main(void) {
ANSELA = 0x00;
TRISA = 0b0100;
TRISAbits.TRISA2 = 1;
LATAbits.LATA0 = 0;
INTCONbits.GIE=1; /* Enable Global Interrupt*/
INTCONbits.PEIE = 1; /* Enable peripheral Interrupt */
OPTION_REGbits.T0CS = 0;
OPTION_REGbits.PSA = 0;
OPTION_REGbits.PS0 = 1; /* set prescaler to 256 */
OPTION_REGbits.PS1 = 1;
OPTION_REGbits.PS2 = 1;
OPTION_REGbits.INTEDG = 0;
TMR0 = 240;
INTCONbits.TMR0IF = 0;
INTCONbits.TMR0IE = 1;
while(1){
}
return;
}
void __interrupt(high_priority) tcInt(void)
{
if (TMR0IE && TMR0IF)
{
TMR0 = 240;
TMR0IF = 0;
if (count == 999)
{
z = 0;
LATAbits.LATA0 = ~LATAbits.LATA0;
count =0;
}
count++;
}
return;
}
You timer calculation is fine but I guess your microcontroller is running at 8 MHz which is the default value after reset if you are working with the internal oscillator (#pragma config FOSC = INTOSC). If you like 16 MHz, you had to do the selection in the OSCCON register.
OSCCON = 0b01110000;
I have covered lately adc and lcd in microcontroller and gone into USART and as usual my first code I make is not working and I need some help with discovering the problem, here's the code:
Transmitter code:
main.c:
#include "config.h"
void main(){
TRISCbits.TRISC6 = 1;
TRISCbits.TRISC7 = 1;
TRISDbits.TRISD0 = 1;
SPBRG = 25;
TXSTAbits.TX9 = 0;
TXSTAbits.SYNC = 0;
TXSTAbits.BRGH = 1;
TXSTAbits.TXEN = 1;
RCSTAbits.SPEN = 1;
RCSTAbits.RX9 = 0;
RCSTAbits.CREN = 0;
while(1){
while(TRMT == 0);
if(PORTDbits.RD0 == 1){
TXREG = 0xFF;
}else{
TXREG = 0;
}
}
}
Receiver code:
main.c:
#include "config.h"
char recieve;
void main(){
TRISCbits.TRISC6 = 1;
TRISCbits.TRISC7 = 1;
TRISDbits.TRISD0 = 0;
PORTDbits.RD0 = 0;
SPBRG = 25;
TXSTAbits.TX9 = 0;
TXSTAbits.SYNC = 0;
TXSTAbits.BRGH = 1;
TXSTAbits.TXEN = 1;
RCSTAbits.SPEN = 1;
RCSTAbits.RX9 = 0;
RCSTAbits.CREN = 0;
while(1){
RCREG = recieve;
if(recieve == 0xFF){
PORTDbits.RD0 = 1;
}else{
PORTDbits.RD0 = 0;
}
}
}
and for both transmitter and receiver projects config.h is a header file where I set the frequency of crystal oscillator and configuration bits so it is the same file/code for both projects
config.h:
/*
* File: config.h
* Author: Fady
*
* Created on August 25, 2014, 1:53 PM
*/
// PIC16F877A Configuration Bit Settings
// 'C' source line config statements
#include <xc.h>
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
// CONFIG
#pragma config FOSC = XT // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = ON // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#define _XTAL_FREQ 4000000
EDIT
I am trying to communicate 2 pic microcontrollers in which if I press the button on D0 in transmitter it sends a 0xFF data and then the receiver checks for if the received data == 0xFF if yes it turns on the LED on D0 in receiver but when I connect it on isis the TX pin of receiver keeps blinking high and low (red and blue) each half a second but when I press the button the high (red) signal keeps for a bit longer but keeps flashing with high and low and I suppose this is for start bit but the receiver doesn't turn on the led that's the error part I don't know what's wrong here
Its just a very stupid silly c programming mistake I wrote:
RCREG = recieve;
which will take the value of receive and assign it to RCREG instead it should be
receive = RCREG;
which will assign the value of RCREG to receive and worked after building...
I am working on pic microcontroller programming and went lately to lcd made 2 codes, one in mplab and the other in mikroc actually both worked in isis but when I tried it in real only mikroc code worked in the microcontroller I don't know actually what is the problem/why did that happen I don't guess this is a hardware or software code because it is same circuit and both codes worked in isis so If anyone wanted to view the code so here it is:
mikroC:
// Lcd pinout settings
sbit LCD_RS at RC0_bit;
sbit LCD_EN at RC1_bit;
sbit LCD_D7 at RB7_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D4 at RB4_bit;
// Pin direction
sbit LCD_RS_Direction at TRISC0_bit;
sbit LCD_EN_Direction at TRISC1_bit;
sbit LCD_D7_Direction at TRISB7_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB4_bit;
void main() {
Lcd_Init();
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
Lcd_Out(1, 3, "Hello!");
}
mplab:
main.c:
#include "config.h"
unsigned char CurvyObject[8] = { 0x01,0x02,0x04,0x08,0x10,0x11,0x1f,0x00 };
void main(){
TRISB = 0;
TRISC = 0;
send_command(0x38);
__delay_us(40);
send_command(0x01);
__delay_ms(1.75);
send_command(0x0C);
__delay_us(40);
moveto(0, 0, 0, 0, 0, 0, 0);
__delay_us(40);
write_character(70);
__delay_us(50);
write_character(97);
__delay_us(50);
write_character(100);
__delay_us(50);
write_character(121);
__delay_us(50);
while(1);
}
config.h:
/*
* File: config.h
* Author: Fady
*
* Created on August 14, 2014, 6:19 PM
*/
// PIC16F877A Configuration Bit Settings
// 'C' source line config statements
#include <xc.h>
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
// CONFIG
#pragma config FOSC = XT
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = ON
#pragma config LVP = ON
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
#define _XTAL_FREQ 4000000
unsigned char i;
//Library Declaration:
void send_command(int command);
void write_character(int character);
void enable_blink();
void moveto(char b6, char b5, char b4, char b3, char b2, char b1, char b0);
void send_command(int command){
PORTB = command;
PORTCbits.RC0 = 0;
enable_blink();
}
void write_character(int character){
PORTB = character;
PORTCbits.RC0 = 1;
enable_blink();
}
void enable_blink(){
PORTCbits.RC1 = 1;
__delay_ms(10);
PORTCbits.RC1 = 0;
__delay_ms(10);
}
void moveto(char b6, char b5, char b4, char b3, char b2, char b1, char b0){
PORTCbits.RC0 = 0;
PORTBbits.RB7 = 1;
PORTBbits.RB6 = b6;
PORTBbits.RB5 = b5;
PORTBbits.RB4 = b4;
PORTBbits.RB3 = b3;
PORTBbits.RB2 = b2;
PORTBbits.RB1 = b1;
PORTBbits.RB0 = b0;
enable_blink();
}
It is a good practice to make sure all peripherals and outputs are in a known state before starting your program.
As mentioned in the comment, you never made sure the LCD has the R/W pin correctly configured.
PORTCbits.RC2=0; // The Microcontroller will always write to the LCD
// Replace RC2 with your R/W pin
In addition to that I compared your LCD library to the one I made and you didn't configure the entry mode, try adding this:
send_command(6); //Cursor Move direction and Display Shift
Check out this generic datasheet to see if you configured the module as desired: http://www.lcd-module.com/eng/pdf/doma/dip162-de.pdf
On a side note, I see that the moveto(); function is used to position the cursor around, may I suggest my approach:
// L1=128,L2=192,L3=144,L4=208
send_command(L1+6); // Go to the 6th character of the first line