|
|
View previous topic :: View next topic |
Author |
Message |
wind88
Joined: 29 Dec 2010 Posts: 37
|
|
Posted: Thu Jan 13, 2011 4:44 am |
|
|
Code: | // flex_lcd.c
// These pins are for the Microchip PicDem2-Plus board,
// which is what I used to test the driver. Change these
// pins to fit your own board.
#define LCD_DB4 PIN_D4
#define LCD_DB5 PIN_D5
#define LCD_DB6 PIN_D6
#define LCD_DB7 PIN_D7
#define LCD_E PIN_E0
#define LCD_RS PIN_E1
#define LCD_RW PIN_E2
// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.
#define USE_LCD_RW 1
//========================================
#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line
int8 const LCD_INIT_STRING[4] =
{
0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
0xc, // Display on
1, // Clear display
6 // Increment cursor
};
//-------------------------------------
void lcd_send_nibble(int8 nibble)
{
// Note: !! converts an integer expression
// to a boolean (1 or 0).
output_bit(LCD_DB4, !!(nibble & 1));
output_bit(LCD_DB5, !!(nibble & 2));
output_bit(LCD_DB6, !!(nibble & 4));
output_bit(LCD_DB7, !!(nibble & 8));
delay_cycles(1);
output_high(LCD_E);
delay_us(2);
output_low(LCD_E);
}
//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine. For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.
#ifdef USE_LCD_RW
int8 lcd_read_nibble(void)
{
int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
#bit retval_0 = retval.0
#bit retval_1 = retval.1
#bit retval_2 = retval.2
#bit retval_3 = retval.3
retval = 0;
output_high(LCD_E);
delay_cycles(1);
retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);
output_low(LCD_E);
return(retval);
}
#endif
//---------------------------------------
// Read a byte from the LCD and return it.
#ifdef USE_LCD_RW
int8 lcd_read_byte(void)
{
int8 low;
int8 high;
output_high(LCD_RW);
delay_cycles(1);
high = lcd_read_nibble();
low = lcd_read_nibble();
return( (high<<4) | low);
}
#endif
//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n)
{
output_low(LCD_RS);
#ifdef USE_LCD_RW
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60);
#endif
if(address)
output_high(LCD_RS);
else
output_low(LCD_RS);
delay_cycles(1);
#ifdef USE_LCD_RW
output_low(LCD_RW);
delay_cycles(1);
#endif
output_low(LCD_E);
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}
//----------------------------
void lcd_init(void)
{
int8 i;
output_low(LCD_RS);
#ifdef USE_LCD_RW
output_low(LCD_RW);
#endif
output_low(LCD_E);
delay_ms(15);
for(i=0 ;i < 3; i++)
{
lcd_send_nibble(0x03);
delay_ms(5);
}
lcd_send_nibble(0x02);
for(i=0; i < sizeof(LCD_INIT_STRING); i++)
{
lcd_send_byte(0, LCD_INIT_STRING[i]);
// If the R/W signal is not used, then
// the busy bit can't be polled. One of
// the init commands takes longer than
// the hard-coded delay of 60 us, so in
// that case, lets just do a 5 ms delay
// after all four of them.
#ifndef USE_LCD_RW
delay_ms(5);
#endif
}
}
//----------------------------
void lcd_gotoxy(int8 x, int8 y)
{
int8 address;
if(y != 1)
address = lcd_line_two;
else
address=0;
address += x-1;
lcd_send_byte(0, 0x80 | address);
}
//-----------------------------
void lcd_putc(char c)
{
switch(c)
{
case '\f':
lcd_send_byte(0,1);
delay_ms(2);
break;
case '\n':
lcd_gotoxy(1,2);
break;
case '\b':
lcd_send_byte(0,0x10);
break;
default:
lcd_send_byte(1,c);
break;
}
}
//------------------------------
#ifdef USE_LCD_RW
char lcd_getc(int8 x, int8 y)
{
char value;
lcd_gotoxy(x,y);
// Wait until busy flag is low.
while(bit_test(lcd_read_byte(),7));
output_high(LCD_RS);
value = lcd_read_byte();
output_low(lcd_RS);
return(value);
}
#endif |
this is the code to initialize the lcd[/quote] |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19568
|
|
Posted: Thu Jan 13, 2011 7:46 am |
|
|
You don't need to set timer0 at all. The timer is running all the time. All the 'set' line does, is set the counter to a value. Just remove the lines setting the timer _especially the one in the interrupt_.
On the printf, %ld.
Best Wishes |
|
|
wind88
Joined: 29 Dec 2010 Posts: 37
|
|
Posted: Thu Jan 13, 2011 9:04 am |
|
|
Code: | #include <16F877A.h>
#device adc=10
#use delay(clock=20000000)
#define XTAL_FREQ 200000000
#include <flex_lcd.c>
#include <stdlib.h>
#FUSES XT, NOWDT,NOPROTECT,NOLVP,NOWDT,PUT,NOBROWNOUT
#use fast_io(B)
#use fast_io(A)
#byte ADRESL = 0xF9E
#byte ADRESH = 0xF1E
#define MAX_VALUE 200
#define CCW_ROTATION MAX_VALUE - 25
#define CW_ROTATION MAX_VALUE - 15
#define STOP_ROTATION MAX_VALUE
#define THRESHOLD_VALUE 65
#define A0 PIN_A0
#define A1 PIN_A1
#define B1 PIN_B1
int8 pulse_max=0;
int8 pulse_top=0;
int8 top_value=0 ;
#INT_TIMER0
static void TIMER0_isr(void)
{
if(INT_TIMER0)// TIMER0 Interrupt Flag
{
pulse_max++; // Pulse Max Increment
pulse_top++; // Pulse Top Increment
/* MAX_VALUE=200 turn off the pulse */
if (pulse_max >= MAX_VALUE) {
pulse_max=0;
pulse_top=0;
output_low(B1); // Turn off RB1
}
if (pulse_top == top_value) {
output_high(B1); // Turn On RB1
}
clear_interrupt(INT_TIMER0);
}
}
void main(void)
{
signed int16 ldr_left ;
signed int16 ldr_right ;
signed int16 ldr_diff ;
port_b_pullups(TRUE);
setup_adc_ports(ALL_ANALOG );
setup_adc(ADC_CLOCK_DIV_32);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
lcd_init();
set_tris_A(0xFF); //port a set as input
set_tris_B(0x00); //port b set as output
output_B(0x00);
// Init Servo Pulse
pulse_max=0;
pulse_top=0;
top_value = MAX_VALUE; // top_value = MAX_VALUE: Servo Motor Stop
// Init TIMER0: Period: Fosc/4 x Prescaler x TMR0
clear_interrupt(INT_TIMER0);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
// Read the ADC here
for(;;){
A0;
set_adc_channel(0);
delay_us(10);
ldr_left=read_adc();
printf(lcd_putc, "\f value = %ld \n",ldr_left);
A1;
set_adc_channel(1);
delay_us(10);
ldr_right=read_adc();
printf(lcd_putc, "value = %ld ",ldr_right);
// Get the different
ldr_diff = ldr_left - ldr_right;
if ((ldr_diff >= -THRESHOLD_VALUE) && (ldr_diff <= THRESHOLD_VALUE))
{
output_low(B1); // Stop the Servo Motor
}
else
{
if (ldr_diff > THRESHOLD_VALUE)
{
top_value = CCW_ROTATION; // Counterclockwise Rotation
}
else
{
top_value = CW_ROTATION; // Clockwise Rotation
}
}
}
}
|
done as u told but the lcd still cant be functioning :(
besides this,my servo motor can turn but it only can turn -90 to +90
omg |
|
|
wind88
Joined: 29 Dec 2010 Posts: 37
|
|
Posted: Thu Jan 13, 2011 9:14 am |
|
|
but without setting the timer0
my servo motor cant even move,but it can move in protues |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19568
|
|
Posted: Thu Jan 13, 2011 9:23 am |
|
|
You still _setup_ the timer. You just don't 'set' it to a value.
The timer still runs, and will reach 0, and the interrupt trigger.
Proteus is not 'God'. In fact it has more faults, than really make it worthwhile. I have the latest full development release, but do not use it for debugging on PIC's, because it is just not reliable. I have more code that doesn't run on Proteus, than does, yet all works in real chips, or in the MPLAB simulator (if properly configured)...
Best Wishes |
|
|
wind88
Joined: 29 Dec 2010 Posts: 37
|
|
Posted: Thu Jan 13, 2011 9:28 am |
|
|
thanx.b4 this i just thought of it would be better if i could test the code in virtual and real hardware
Code: | #include <16F877A.h>
#device adc=10
#use delay(clock=20000000)
#define XTAL_FREQ 200000000
#include <flex_lcd.c>
#include <stdlib.h>
#FUSES XT, NOWDT,NOPROTECT,NOLVP,NOWDT,PUT,NOBROWNOUT
#use fast_io(B)
#use fast_io(A)
#byte ADRESL = 0xF9E
#byte ADRESH = 0xF1E
#define MAX_VALUE 200
#define CCW_ROTATION MAX_VALUE - 25
#define CW_ROTATION MAX_VALUE - 15
#define STOP_ROTATION MAX_VALUE
#define THRESHOLD_VALUE 65
#define A0 PIN_A0
#define A1 PIN_A1
#define B1 PIN_B1
int8 pulse_max=0;
int8 pulse_top=0;
int8 top_value=0 ;
#INT_TIMER0
static void TIMER0_isr(void)
{
if(INT_TIMER0)// TIMER0 Interrupt Flag
{
pulse_max++; // Pulse Max Increment
pulse_top++; // Pulse Top Increment
/* MAX_VALUE=200 turn off the pulse */
if (pulse_max >= MAX_VALUE) {
pulse_max=0;
pulse_top=0;
output_low(B1); // Turn off RB1
}
if (pulse_top == top_value) {
output_high(B1); // Turn On RB1
}
clear_interrupt(INT_TIMER0);
}
}
void main(void)
{
signed int16 ldr_left ;
signed int16 ldr_right ;
signed int16 ldr_diff ;
port_b_pullups(TRUE);
setup_adc_ports(ALL_ANALOG );
setup_adc(ADC_CLOCK_DIV_32);
setup_spi(SPI_SS_DISABLED);
lcd_init();
set_tris_A(0xFF); //port a set as input
set_tris_B(0x00); //port b set as output
output_B(0x00);
// Init Servo Pulse
pulse_max=0;
pulse_top=0;
top_value = MAX_VALUE; // top_value = MAX_VALUE: Servo Motor Stop
// Init TIMER0: Period: Fosc/4 x Prescaler x TMR0
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
// Read the ADC here
for(;;){
A0;
set_adc_channel(0);
delay_us(10);
ldr_left=read_adc();
printf(lcd_putc, "\f value = %ld \n",ldr_left);
A1;
set_adc_channel(1);
delay_us(10);
ldr_right=read_adc();
printf(lcd_putc, "value = %ld ",ldr_right);
// Get the different
ldr_diff = ldr_left - ldr_right;
if ((ldr_diff >= -THRESHOLD_VALUE) && (ldr_diff <= THRESHOLD_VALUE))
{
output_low(B1); // Stop the Servo Motor
}
else
{
if (ldr_diff > THRESHOLD_VALUE)
{
top_value = CCW_ROTATION; // Counterclockwise Rotation
}
else
{
top_value = CW_ROTATION; // Clockwise Rotation
}
}
}
}
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9255 Location: Greensville,Ontario
|
|
Posted: Thu Jan 13, 2011 9:31 am |
|
|
Proteus is a 'simulation' NOT the real world and is FULL of bugs, errors, etc. and not worth the money you paid for it!
What kind of servo motor? I'll bet it's a RC style and if so they only go +-90* from center positon(unless modified).If it's a normal servo, what's the feedback and position sensors? Pots, encoders,??BTW what power supply for the servo? Does the servo work in another program or hardware?
Looks like you're still using TRIS statements, and unless you're an expert, you can really mess the program up( ie: 'doesn't work') by misusing TRIS() !
You are NOT supposed to clear interrupts in your ISR, the compiler does that for you.
Do not use fastio() unless you're an expert, same as tris() problems !!!
Again, let the compiler handle it all....it does work, unlike Proteus !! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19568
|
|
Posted: Thu Jan 13, 2011 9:34 am |
|
|
You still need to _setup_ the timer:
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);
You just don't ever need to _set_ it:
set_timer0(206) ; //interrupt every 0.1ms
or
set_timer0(0);
Get rid of these.....
Best Wishes |
|
|
wind88
Joined: 29 Dec 2010 Posts: 37
|
|
Posted: Thu Jan 13, 2011 9:37 am |
|
|
It is a normal servo that can turn from -90 to +90 degree and can even stop at 0 degree (I test it with the test code for servo).
The position sensor is from ldr and it have a potentiometer inside it.
Erm, for the tris part, if I don't use it, the servo can't even turn too. Sorry for that.
I will delete the tris part.
I will delete the clear interrupt part too. thanx |
|
|
wind88
Joined: 29 Dec 2010 Posts: 37
|
|
Posted: Thu Jan 13, 2011 9:39 am |
|
|
Code: | #include <16F877A.h>
#device adc=10
#use delay(clock=20000000)
#define XTAL_FREQ 200000000
#include <flex_lcd.c>
#include <stdlib.h>
#FUSES XT, NOWDT,NOPROTECT,NOLVP,NOWDT,PUT,NOBROWNOUT
#define MAX_VALUE 200
#define CCW_ROTATION MAX_VALUE - 25
#define CW_ROTATION MAX_VALUE - 15
#define STOP_ROTATION MAX_VALUE
#define THRESHOLD_VALUE 65
#define A0 PIN_A0
#define A1 PIN_A1
#define B1 PIN_B1
int8 pulse_max=0;
int8 pulse_top=0;
int8 top_value=0 ;
#INT_TIMER0
static void TIMER0_isr(void)
{
if(INT_TIMER0)// TIMER0 Interrupt Flag
{
pulse_max++; // Pulse Max Increment
pulse_top++; // Pulse Top Increment
/* MAX_VALUE=200 turn off the pulse */
if (pulse_max >= MAX_VALUE) {
pulse_max=0;
pulse_top=0;
output_low(B1); // Turn off RB1
}
if (pulse_top == top_value) {
output_high(B1); // Turn On RB1
}
}
}
void main(void)
{
signed int16 ldr_left=0 ;
signed int16 ldr_right=0 ;
signed int16 ldr_diff=0 ;
port_b_pullups(TRUE);
setup_adc_ports(ALL_ANALOG );
setup_adc(ADC_CLOCK_DIV_32);
setup_spi(SPI_SS_DISABLED);
lcd_init();
// Init Servo Pulse
pulse_max=0;
pulse_top=0;
top_value = MAX_VALUE; // top_value = MAX_VALUE: Servo Motor Stop
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
// Read the ADC here
for(;;){
A0;
set_adc_channel(0);
delay_us(10);
ldr_left=read_adc();
printf(lcd_putc, "\f value = %ld \n",ldr_left);
A1;
set_adc_channel(1);
delay_us(10);
ldr_right=read_adc();
printf(lcd_putc, "value = %ld ",ldr_right);
// Get the different
ldr_diff = ldr_left - ldr_right;
if ((ldr_diff >= -THRESHOLD_VALUE) && (ldr_diff <= THRESHOLD_VALUE))
{
output_low(B1); // Stop the Servo Motor
}
else
{
if (ldr_diff > THRESHOLD_VALUE)
{
top_value = CCW_ROTATION; // Counterclockwise Rotation
}
else
{
top_value = CW_ROTATION; // Clockwise Rotation
}
}
}
}
|
|
|
|
wind88
Joined: 29 Dec 2010 Posts: 37
|
|
Posted: Fri Jan 14, 2011 5:07 am |
|
|
Quote: | #include <16F877A.h>
#device adc=10
#use delay(clock=1000000)
#define XTAL_FREQ 40000000
#FUSES XT, NOWDT,NOPROTECT,NOLVP,NOWDT,PUT,NOBROWNOUT
#define MAX_VALUE 200
#define CCW_ROTATION MAX_VALUE - 25
#define CW_ROTATION MAX_VALUE - 15
#define STOP_ROTATION MAX_VALUE
#define THRESHOLD_VALUE 35
#define A0 PIN_A0
#define A1 PIN_A1
#define B1 PIN_B1
unsigned char pulse_max=0;
unsigned char pulse_top=0;
unsigned char top_value=0 ;
#INT_TIMER0
static void TIMER0_isr(void)
{
if(INT_TIMER0)// TIMER0 Interrupt Flag
{
pulse_max++; // Pulse Max Increment
pulse_top++; // Pulse Top Increment
/* MAX_VALUE=200 turn off the pulse */
if (pulse_max >= MAX_VALUE) {
pulse_max=0;
pulse_top=0;
output_low(B1); // Turn off RB1
}
if (pulse_top == top_value) {
output_high(B1); // Turn On RB1
}
}
}
void main(void)
{
signed int16 ldr_left=0 ;
signed int16 ldr_right=0 ;
signed int16 ldr_diff ;
port_b_pullups(TRUE);
setup_adc_ports(ALL_ANALOG );
setup_adc(ADC_CLOCK_DIV_8);
setup_spi(SPI_SS_DISABLED);
// Init Servo Pulse
pulse_max=0;
pulse_top=0;
top_value = MAX_VALUE; // top_value = MAX_VALUE: Servo Motor Stop
// Init TIMER0: Period: Fosc/4 x Prescaler x TMR0
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
// Read the ADC here
for(;;){
set_adc_channel(0);
delay_us(10);
ldr_left=read_adc();
set_adc_channel(1);
delay_us(10);
ldr_right=read_adc();
// Get the different
ldr_diff = ldr_left - ldr_right;
if ((ldr_diff >= -THRESHOLD_VALUE) && (ldr_diff <= THRESHOLD_VALUE))
{
output_low(B1); // Stop the Servo Motor
}
else
{
if (ldr_diff > THRESHOLD_VALUE)
{
top_value = CCW_ROTATION; // Counterclockwise Rotation
}
else
{
top_value = CW_ROTATION; // Clockwise Rotation
}
}
}
}
|
erm for the xtal and #delay, is it correct?
i tried 20mhz and 4mhz crystal but the code seem to have no effect on the servo motor |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19568
|
|
Posted: Fri Jan 14, 2011 5:18 am |
|
|
Of course it _isn't_. Read what I say. You must _setup_ the timer. Just don't 'set' it. Unless you use setup, the timer is not running.
Best Wishes |
|
|
wind88
Joined: 29 Dec 2010 Posts: 37
|
|
Posted: Fri Jan 14, 2011 7:21 am |
|
|
Sorry about that, I miss the part.
Thanx a lot Ttelmah |
|
|
wind88
Joined: 29 Dec 2010 Posts: 37
|
|
Posted: Fri Jan 14, 2011 2:28 pm |
|
|
Code: | #include <16F877A.h>
#device adc=10
#use delay(clock=5000000)
#define XTAL_FREQ 200000000
#include <flex_lcd.c>
#FUSES HS, NOWDT,NOPROTECT,NOLVP,NOWDT,PUT,NOBROWNOUT
#include <stdio.h>
#define MAX_VALUE 200
#define CCW_ROTATION MAX_VALUE - 25
#define CW_ROTATION MAX_VALUE - 15
#define STOP_ROTATION MAX_VALUE
#define THRESHOLD_VALUE 25
#define A0 PIN_A0
#define A1 PIN_A1
#define B1 PIN_B1
unsigned char pulse_max=0;
unsigned char pulse_top=0;
unsigned char top_value=0 ;
#INT_TIMER0
static void TIMER0_isr(void)
{
if(INT_TIMER0)// TIMER0 Interrupt Flag
{
pulse_max++; // Pulse Max Increment
pulse_top++; // Pulse Top Increment
/* MAX_VALUE=200 turn off the pulse */
if (pulse_max >= MAX_VALUE) {
pulse_max=0;
pulse_top=0;
output_low(B1); // Turn off RB1
}
if (pulse_top == top_value) {
output_high(B1); // Turn On RB1
}
}
}
void main(void)
{
unsigned int16 ldr_left=0 ;
unsigned int16 ldr_right=0 ;
unsigned int16 ldr_diff ;
port_b_pullups(TRUE);
setup_adc_ports(ALL_ANALOG );
setup_adc(ADC_CLOCK_DIV_32);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
lcd_init();
// Init Servo Pulse
pulse_max=0;
pulse_top=0;
top_value = MAX_VALUE; // top_value = MAX_VALUE: Servo Motor Stop
// Init TIMER0: Period: Fosc/4 x Prescaler x TMR0
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
// Read the ADC here
while(1){
set_adc_channel(0);
delay_us(10);
ldr_left=read_adc();
printf(lcd_putc, "\f value = %ld \n",ldr_left);
set_adc_channel(1);
delay_us(10);
ldr_right=read_adc();
printf(lcd_putc, "value = %ld ",ldr_right);
// Get the different
ldr_diff = ldr_left - ldr_right;
if ((ldr_diff >= -THRESHOLD_VALUE) && (ldr_diff <= THRESHOLD_VALUE))
{
output_low(B1); // Stop the Servo Motor
}
else
{
if (ldr_diff > THRESHOLD_VALUE)
{
top_value = CCW_ROTATION; // Counterclockwise Rotation
}
else
{
top_value = CW_ROTATION; // Clockwise Rotation
}
}
}
}
|
For the adc to display, is there anything I need to add? As this can't made the lcd display value. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19568
|
|
Posted: Fri Jan 14, 2011 3:47 pm |
|
|
You have XTAL_FREQ set to 200MHz, and the clock to 5HMz....
The clock statement, _must_ match your real crystal frequency. Otherwise nothing involving timings will work correctly.
Setting clock down to 5MHz, _whatever the real frequency of your oscillator_, will take you back to possibly not being able to complete the timer interrupt code in time.
You don't need to test the timer0 flag in the interrupt. The only way to get to the routine, is that the interrupt _has_ triggered. INT_TIMER0, is _not_ the timer 0 interrupt flag anyway. It is a fixed value defined in the header file.
A routine, cannot be defined as 'static'. Pointless.
You have gone back to using unsigned. means that if ldr_right, is greater than ldr_left, you _will_ get an invalid value in ldr_diff...
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|