I am having problems with the ReadAD10 function, currently it is outputting 8-bit range values (0-255) instead of the proper 10-bit range (0-1023). I have a 100k pot wired up to AN0 and I am periodically polling the values of the 10bit output, displaying them on an attached LCD. The LCDWord function is working fine so that can be ruled out. I suspected a problem with the data formatting but the code seems fine to me. Also another suspect area is the chip definition file, as in the following sniplet. However I was able to confirm that ADRESL is defined, so it should output the 10 bit value properly. I'm a little stumped at what's happening.
I think you just need to switch your high and low bytes of the ReadAD10. So instead of:
ReadAD10_H = ADRESH
ReadAD10 = ADRESL
use;
ReadAD10 = ADRESL
ReadAD10_H = ADRESH
Quote from Hugh: "When copying two bytes into a word, it is important to copy the low byte first. This is because the high byte of the word var is cleared when the word var is set to a byte value or variable."
Kent
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Oops, no that wasn't it Kent. I had switched them to test if changing the order would make any difference. I just tried switching them back and it makes no difference.
I believe I have narrowed down the problem though. I suspected there may be a problem with using functions and words (it may have been broken in Hugh's new updates) and I wrote some code to test it.
sub test_function_word #nr
Dim test_var As word
test_var = test_word
cls
LCDWord(test_var)
SerialTXWord(test_var)
end sub
word function test_word
test_word = 9999
end function
The function is expected to display 9999 on the LCD and the terminal but interestingly enough it displays 15. If I have some free time later i'm going to go compare the two source codes to see whats up.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Sorry to drag this out some more. But just some observations, since going back to the 4bit LCD routines. Downloaded latest zip, and still had the problem with LCDWord.
Back when I was re-inventing the wheel,(i.e. an ascii LCD function for my serial LCD), I forgot to extend Hugh's routine to include 1,000's an 10,000' divisions. Also noted at the time that "dim LCDTempValue as word" was needed to make my seperate header file work. So if you put the above statement in the old lcd.h file, everything seems to work fine for me (using a 16f88). This might also work for the new lcd.h but did not try.
Kent
Find this line in old lcd.h:
sub LCDWord(LCDValue as word) #NR
dim LCDValueTemp as word 'this makes everything o.k.
'******************************
'Test 4 bit LCDWord routine
'******************************
I tried your test code out with the new files and indeed they work. However the following program as I mentioned in my other thread still produces errors.
sub test_function_t #nr
Dim test_var As Word
test_var = test_function
end sub
word function test_function
test_function = 9999
end function
Main:
Dim test_var As Word
test_var = test_function
end
I suppose there must be some incorrect type detection going on here, particularly if the subroutine is compiled before the function, as the same code will compile fine without the included subroutine. The asm output is below.
;Program compiled by Great Cow BASIC (0.9 12/6/2007)
;Need help? See the GCBASIC forums at http://sourceforge.net/forum/?group_id=169286,
;check the documentation or email hconsidine@bigpond.com.
;Set up the assembler options (Chip type, clock source, other bits and pieces)
LIST p=16F876A, r=DEC
#include <P16F876A.inc>
__CONFIG _HS_OSC & _WDT_OFF & _LVP_OFF
;Start of the main program
MAIN
call FN_TEST_FUNCTION
movf TEST_FUNCTION,W
movwf TEST_VAR
clrw
movwf TEST_VAR_H
goto BASPROGRAMEND
BASPROGRAMEND
sleep
goto $
;********************************************************************************
;Subroutines included in program
;********************************************************************************
Tam and Hugh,
Tried the READAD10 for the first time, very nice! I was able to compile the short code below for a 16f88 at 20mhz, and a 4 bit LCD. Hooked up a 50K pot to +5V, AN0 on the wiper, and GND. O.K., NOW there is a current limiting 330ohm resistor in series with AN0. The results were from 0 to 1023, which I believe is your 10 bits.
The function works also as expected. Have not looked into the specific A2D registers of your device and how GCBasic a-d.h handles them. So, there still could be a problem for you?
If questions remain about calling a function or sub from within a sub or function, then you should start a new thread. Your construction of the example is at fault, as opposed to GCBasic.
Kent
'.......
word function test_function
test_function = 9999
end function
Main:
cls
LCDWord test_function
locate 1,0
LCDWord ReadAD10(A0)
wait 2 s
goto Main
I can't see what is wrong in my example. I declared a Word value and I am assigning the value from the function test_function to the word. However this code works if the above subroutine is not included, or the function is in code before the subroutine, which I find to be very odd. As for a-d.h, the variable ADRESL is defined therefore the code should work and does work fine whenever there is NOT a subroutine declared.
However once a subroutine is declared in code, the function breaks.
For example the following code using your code with the 877 and an added subroutine produces the following code.
;Start of the main program
MAIN
call NO_USE
call CLS
call FN_TEST_FUNCTION
movf TEST_FUNCTION,W
movwf LCDVALUE
clrw
movwf LCDVALUE_H
call LCDWORD
movlw 1
movwf LCDLINE
clrf LCDCOLUMN
call LOCATE
movf A0,W
movwf ADREADPORT
call FN_READAD10
movf READAD10,W
movwf LCDVALUE
clrw
movwf LCDVALUE_H
call LCDWORD
movlw 2
movwf SysWaitTempS
call Delay_S
goto MAIN
BASPROGRAMEND
sleep
goto $
It in fact clears the upper nibble thus only producing 0-255. In the sourcecode there is a section dealing with type detection, and if the function is not detected as a word function, then the code is produced. Therefore I reason that there is a problem with type detection.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Tam, there was a problem with the type detection caused by a bug in the TypeOfVar function. I've just fixed this, and the code you posted in the other thread now compiles fine.
Also, #nr is only needed where there are parameters that you do not want copied back - if there are no parameters, you can leave it out.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Tam, sorry for my mis-understanding, I just saw a subroutine that was not called from main (which normally isn't an issue). But I also noticed that there might be some contention between the subroutine and main over who owned the duplicate statement of test_var = test_function. So on the surface, it looked to be a hypothetical case, that un-nessarily caused the problem.
Woke up and plugged in the board this morning and no go on READAD10, so couldn't try your no_use sub. Looks like more troubleshooting, oh joy.
Kent
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hugh,
I am having problems with the ReadAD10 function, currently it is outputting 8-bit range values (0-255) instead of the proper 10-bit range (0-1023). I have a 100k pot wired up to AN0 and I am periodically polling the values of the 10bit output, displaying them on an attached LCD. The LCDWord function is working fine so that can be ruled out. I suspected a problem with the data formatting but the code seems fine to me. Also another suspect area is the chip definition file, as in the following sniplet. However I was able to confirm that ADRESL is defined, so it should output the 10 bit value properly. I'm a little stumped at what's happening.
PIC16F876A
'Write output
#IFDEF Var(ADRESL)
ReadAD10_H = ADRESH
ReadAD10 = ADRESL
#ENDIF
#IFDEF NoVar(ADRESL)
ReadAD10 = ADRES
#ENDIF
I remember this function working properly before (I am running the version you have updated) and I am not sure what is broken.
My code is similar to the following:
Loopy:
Dim Temperature As Word
Temperature = ReadAD10(AN0)
LCDWord(Temperature)
Wait 500 ms
Goto Loopy
Is there anything I should be doing that I may be forgetting? Thanks!
I think you just need to switch your high and low bytes of the ReadAD10. So instead of:
ReadAD10_H = ADRESH
ReadAD10 = ADRESL
use;
ReadAD10 = ADRESL
ReadAD10_H = ADRESH
Quote from Hugh: "When copying two bytes into a word, it is important to copy the low byte first. This is because the high byte of the word var is cleared when the word var is set to a byte value or variable."
Kent
Oops, no that wasn't it Kent. I had switched them to test if changing the order would make any difference. I just tried switching them back and it makes no difference.
I believe I have narrowed down the problem though. I suspected there may be a problem with using functions and words (it may have been broken in Hugh's new updates) and I wrote some code to test it.
sub test_function_word #nr
Dim test_var As word
test_var = test_word
cls
LCDWord(test_var)
SerialTXWord(test_var)
end sub
word function test_word
test_word = 9999
end function
The function is expected to display 9999 on the LCD and the terminal but interestingly enough it displays 15. If I have some free time later i'm going to go compare the two source codes to see whats up.
Tam and Kent, you're both right. The bytes were being set the wrong way around, and there was also a problem with the passing of parameters.
I'm pretty sure I've been able to fix this bug - I've just successfully run this program on an 18F4550:
#include "mytest.h"
Print "A/D Test"
Wait 1 sec
Do
CLS
LCDWord ReadAD10(AN0)
Wait 100 ms
loop
(mytest.h has LCD port settings, #chip and #config directives)
Fixed files are in the usual place - http://gcbasic.sourceforge.net/newfiles/update.zip
Sorry to drag this out some more. But just some observations, since going back to the 4bit LCD routines. Downloaded latest zip, and still had the problem with LCDWord.
Back when I was re-inventing the wheel,(i.e. an ascii LCD function for my serial LCD), I forgot to extend Hugh's routine to include 1,000's an 10,000' divisions. Also noted at the time that "dim LCDTempValue as word" was needed to make my seperate header file work. So if you put the above statement in the old lcd.h file, everything seems to work fine for me (using a 16f88). This might also work for the new lcd.h but did not try.
Kent
Find this line in old lcd.h:
sub LCDWord(LCDValue as word) #NR
dim LCDValueTemp as word 'this makes everything o.k.
'******************************
'Test 4 bit LCDWord routine
'******************************
'Chip model
#chip 16f88,20
#config _CP_OFF & CPD_OFF &_WDT_OFF & _BODEN_OFF & _PWRTE_ON & _HS_OSC & _LVP_OFF & _MCLR_ON
'Setup 4 bit LCD
#define LCD_IO 4
#define LCD_DB4 PORTB.5
#define LCD_DB5 PORTB.6
#define LCD_DB6 PORTB.7
#define LCD_DB7 PORTB.0
#define LCD_RS PORTA.4
#define LCD_RW PORTA.3
#define LCD_Enable PORTA.2
#define Switch PORTB.2
dim testx as word
dim T1 as word
dir Switch In
InitTimer1 Osc, PS1_1/8
Print "Hello World"
wait 1 s
Start:
ClearTimer 1
Wait until Switch Off
wait 10 ms
StartTimer 1
Wait until Switch On
StopTimer 1
T1 = TMR1L
T1_H = TMR1H
cls
LCDWord (T1)
locate 1,0
testx = 59999
LCDWord (testx)
wait 1 s
Goto Start
Hugh,
I tried your test code out with the new files and indeed they work. However the following program as I mentioned in my other thread still produces errors.
#chip 16F876A, 20
#config HS_OSC, WDT_OFF, LVP_OFF
sub test_function_t #nr
Dim test_var As Word
test_var = test_function
end sub
word function test_function
test_function = 9999
end function
Main:
Dim test_var As Word
test_var = test_function
end
I suppose there must be some incorrect type detection going on here, particularly if the subroutine is compiled before the function, as the same code will compile fine without the included subroutine. The asm output is below.
;Program compiled by Great Cow BASIC (0.9 12/6/2007)
;Need help? See the GCBASIC forums at http://sourceforge.net/forum/?group_id=169286,
;check the documentation or email hconsidine@bigpond.com.
;********************************************************************************
;Set up the assembler options (Chip type, clock source, other bits and pieces)
LIST p=16F876A, r=DEC
#include <P16F876A.inc>
__CONFIG _HS_OSC & _WDT_OFF & _LVP_OFF
;********************************************************************************
;Set aside memory locations for variables
TEST_FUNCTION equ 32
TEST_FUNCTION_H equ 33
TEST_VAR equ 34
TEST_VAR_H equ 35
;********************************************************************************
;Jump to initialisation code when PIC is reset
ORG 0
call INITSYS
goto SystemInitialise
;********************************************************************************
;Interrupt vector
ORG 4
retfie
;********************************************************************************
;Various initialisation routines, automatically called by GCBASIC
SystemInitialise
;********************************************************************************
;Start of the main program
MAIN
call FN_TEST_FUNCTION
movf TEST_FUNCTION,W
movwf TEST_VAR
clrw
movwf TEST_VAR_H
goto BASPROGRAMEND
BASPROGRAMEND
sleep
goto $
;********************************************************************************
;Subroutines included in program
;********************************************************************************
FN_TEST_FUNCTION
movlw 39
movwf TEST_FUNCTION_H
movlw 15
movwf TEST_FUNCTION
return
;********************************************************************************
INITSYS
clrf PORTA
clrf PORTB
clrf PORTC
movlw 7
banksel CMCON
movwf CMCON
banksel ADCON0
bcf ADCON0,ADON
banksel ADCON1
bcf ADCON1,ADFM
bcf ADCON1,PCFG3
bsf ADCON1,PCFG2
bsf ADCON1,PCFG1
bcf ADCON1,PCFG0
banksel STATUS
return
;********************************************************************************
END
The only workaround right now is to add some inline asm after the call.
Main:
Dim test_var As Word
test_var = test_function
movf test_function_h,W ***
movwf test_var ***
end
Tam and Hugh,
Tried the READAD10 for the first time, very nice! I was able to compile the short code below for a 16f88 at 20mhz, and a 4 bit LCD. Hooked up a 50K pot to +5V, AN0 on the wiper, and GND. O.K., NOW there is a current limiting 330ohm resistor in series with AN0. The results were from 0 to 1023, which I believe is your 10 bits.
The function works also as expected. Have not looked into the specific A2D registers of your device and how GCBasic a-d.h handles them. So, there still could be a problem for you?
If questions remain about calling a function or sub from within a sub or function, then you should start a new thread. Your construction of the example is at fault, as opposed to GCBasic.
Kent
'.......
word function test_function
test_function = 9999
end function
Main:
cls
LCDWord test_function
locate 1,0
LCDWord ReadAD10(A0)
wait 2 s
goto Main
this is a test:
[html]Main:
cls
LCDWord test_function
locate 1,0
LCDWord ReadAD10(A0)
wait 2 s
goto Main[html]
Kent,
I can't see what is wrong in my example. I declared a Word value and I am assigning the value from the function test_function to the word. However this code works if the above subroutine is not included, or the function is in code before the subroutine, which I find to be very odd. As for a-d.h, the variable ADRESL is defined therefore the code should work and does work fine whenever there is NOT a subroutine declared.
However once a subroutine is declared in code, the function breaks.
For example the following code using your code with the 877 and an added subroutine produces the following code.
;Start of the main program
MAIN
call NO_USE
call CLS
call FN_TEST_FUNCTION
movf TEST_FUNCTION,W
movwf LCDVALUE
clrw
movwf LCDVALUE_H
call LCDWORD
movlw 1
movwf LCDLINE
clrf LCDCOLUMN
call LOCATE
movf A0,W
movwf ADREADPORT
call FN_READAD10
movf READAD10,W
movwf LCDVALUE
clrw
movwf LCDVALUE_H
call LCDWORD
movlw 2
movwf SysWaitTempS
call Delay_S
goto MAIN
BASPROGRAMEND
sleep
goto $
Note in particular the call to the function:
call FN_TEST_FUNCTION
movf TEST_FUNCTION,W
movwf LCDVALUE
clrw
movwf LCDVALUE_H
It in fact clears the upper nibble thus only producing 0-255. In the sourcecode there is a section dealing with type detection, and if the function is not detected as a word function, then the code is produced. Therefore I reason that there is a problem with type detection.
Forgot the subroutine:
sub no_use #nr
nop
end sub
Tam, there was a problem with the type detection caused by a bug in the TypeOfVar function. I've just fixed this, and the code you posted in the other thread now compiles fine.
Also, #nr is only needed where there are parameters that you do not want copied back - if there are no parameters, you can leave it out.
Tam, sorry for my mis-understanding, I just saw a subroutine that was not called from main (which normally isn't an issue). But I also noticed that there might be some contention between the subroutine and main over who owned the duplicate statement of test_var = test_function. So on the surface, it looked to be a hypothetical case, that un-nessarily caused the problem.
Woke up and plugged in the board this morning and no go on READAD10, so couldn't try your no_use sub. Looks like more troubleshooting, oh joy.
Kent