and not "XXXX". So I have data coming in, I am scaling it and I want to display it on an GLCD. 10V shows up at 1000, 9.90V shows up as 990V, etc etc. I want it to show up as "10.00V" or "1.024A", etc etc. Normally I know I could convert it to a string, and pad it. But here is the caveat: Im running low on memory. The program barks at me if I try to convert things to a string. Currently I have used up 90-95% of my PICs program and Ive tried to slim things down as much as I can, but the scaling takes up a ton of program space. Now I would be OK with it showing up as is; BUT when the voltage being read back is less than 1000 (or 4 digits) the last digit still stays on screen. A current work around is to basically clear the screen when I turn the encoders. Its lazy but it works.
Ive tried a few things, but most of them have lead to dead ends. So I figured Id ask here. See lines 220 to 226 (The GLCD print commands)
I see the following options:
1) De-solder the PIC and upgrade to the same family but with more memory (I think theres one with 2k program memory).
2) Downgrade to a smaller I2C GLCD .
3) Use a nextion GLCD-but this is slightly pricey. The one advantage this has is that I can also implement an NTC temperature sensor to control the heatsink fan since I will have more room for code. I can also do a lot more with the screen and not have to worry about the PIC being bogged down by sending data to the screen all the time.
4) Make/design a small board to interface to the GLCD I want and just off load the commands to it, and send the commands via UART. I know where I want things, I could just program this PIC to display data. This is more of a coding exercise though.
Non relevant info: The project is an adjustable bench power supply. Ive written my own encoder function based on one I found for arduino. The two encoders adjust the voltage and current limits. Voltage and current is read back to a screen. I havent packed it up yet, but it does work pretty nicely. Next post will have the mostly done schematics.
Thanks for the help-Currently at work so any code changes will have to be done tonight.
Your code would be more relevant to you query than the schematic is but, from what you have described, if you are managing to display xxxxV can you not use fixed point and send 2 chr's, point, 2chr's, 'V' ?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Gave this a shot, and I still only have room for one Str conversion, 96.53%. I can convert it to a string, but any manipulation (like left padding), and I run out of memory.
I have a sinking feeling my options are running out.
Edit: as of 9/27, 7:13PM EST. They have the larger device in production (F1778) which has 28k program space. Might as well go over board right?
Tried Recompiling the program with the chip options
PIC16F1776 or PIC16F1778
and I get an error
"BenchtopPSU20210927AWithGLCD.gcb (185): Error: Variable ADPREF was not explicitly declared"
Using version:
0.98.07 2021-05-27 (Windows 64 bit)
Interesting. Nothing else has changed.
Edit #2 @7:26PM.
Added in the lines
ADPREF,ADCON1,1
ADPREF,ADCON1,0
On line 2624 and 2625 respectively and this fixes it. Compiles with 50% Program space used
1778 Chip compiles as well if I make the same mods :). I think we have the obvious solution, even though its a slight PITA to de-solder an SOIC....that is if I can find the chip :(
Last edit: Chris S 2021-09-27
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Sorry for the later response. I had to wait to engineer another project to justify shipping costs on a few PICs. But Now ive upgraded to a 16F1778. This code works perfectly and I have more than enough ram + program memory to do other things with it as well. So I thank you and everyone else for your input.
But now I am on to the next set of problems: The ADC responds too quick and the values change quickly under load even though they stay the same on my meter. When no load is present its fine and reads a perfect 1000mV (10.00V). Under load, it varies from 9700 to 9800. Im guessing its picking up the noise from loading down the rail.
I had this problem once before, and I forgot how I solved it.
Last edit: Chris S 2021-11-18
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I think I need a delay, or something else but I suspect a few things:
1) Noise on the 5V rail when loaded (its not the rail being loaded though). I am using a solid voltage reference though. I dont suspect its this but I'll check the 5V rail when the main rail is being loaded anyway.
2) Noise from the output being picked up by the ADC. In this case it would be the 120Hz waveform from the filter caps making it through the pass transistor. I suspect its picking up the peaks and valleys. I'll have to confirm values with my oscilloscope.
3) Quantum mechanics. If I look away it will probably work but observing the circuit collapses its function and the outcome changes 🤣
What Ive implemented so far: Run timer 1 at one second intervals and read the ADC then. Using this method, it still happens. The only slight issue this causes is that I dont see the change on the screen if Im changing the voltage.
For #2 maybe an averaging function would work?
Other possibilities: Maybe heat killed my op-amp again from being near the PIC being desoldered?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Add a small capacitor across the ADC input? Depending on your resistive divider 10nF to 100nF or so? You could solder/connect the capacitor directly across the lower portion of the resistive divider.
Of course averaging consecutive ADC readings would work just as well.
Not forgetting where and how the negative return is connected on the circuit you are measuring the voltage of.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I think I have a clue as to whats going on. Makes no sense but here we are. My voltage reference gets dragged down when a load is placed on the main circuit. Heres the kicker: That voltage reference isnt tied to anything else BUT the PIC micro 😕 😕 😕
I mean, the PIC ADC shouldnt take up much current from the voltage reference. Maybe I'll reduce the resistor value and see if that fixes it. So it doesnt seem to be software. But Im tired.
So, I did de-solder and resolder this reference. Maybe I ruined it?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You know whats strange? Notepad++ can usually open files with no problem. It opens the .dat files but for some reason, doesnt show the ADC registers. They show up properly if I open it up in GCCB.
PIC16LF1779-No Ref
PIC16LF1778- No Ref. Shows it but I think I modified it.
PIC16LF1777-No Ref
PIC16LF1776-No Ref
PIC16LF1773-No Ref
PIC16F1779-No ADPREF
PIC16F1778-No Pref (but I know I modified this one last night)
PIC16F1777-No ADPREF
PIC16F1776-Has ADPREF. I possibly modified this one.
PIC16F1773-Has ADPREF
I have one more thing to try before work. I'll open up MBLabX and start a project there with the 1779
Last edit: Chris S 2021-09-28
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I will add to the generation process a fix to resolve the issue in Great Cow BASIC.
Re MPLAB-X if you are using 5.xx then the compiler does not use the INC files. The way to test... is to select MPASM as the compiler in Great Cow BASIC. And, MPASM cannot parse ADPREF
Also, more importantly. Where you set ADPREF = 10 this is wrong. Very wrong.
This is the correct change
ADPREF1,ADCON1,1
ADPREF0,ADCON1,0
ADPREF is two bits of register ADCON1 therefore you cannot set to 10. If you use the change you used you will simply incorrectly set bits in ADCON1. To be clear ADPREF does not exist as a register or byte. And, should not be created as such. ADPREF0 and ADPREF1 are bits. To set these bits use a ADCON1 mask, an alias, or directly set as follows;
ADPREF1 = 1
ADPREF0= 0
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
@Chris S "10V shows up at 1000, 9.90V shows up as 990V, etc etc. I want it to show up as "10.00V"
divide number ie 990 by 100 and print
then print "."
then divide 990 by 10 and print
should get 9.99
edit think it need mod
Last edit: stan cartwright 2021-09-29
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
//ADC Setup
ADPREF=10 ;ext vref
ADCON1.1=1
ADCON1.0=0
ADON=1 ;Turn the ADC on
ADCON1=0b11100010
This can be reduced to :
//ADC Setup
ADON=1 ;Turn the ADC on
ADCON1=0b11100010
There is no need to set the ADCON1.1 and ADCON1.0 bits twice
There is also no need to Set "ADON = 1" If you are using READAD or READAD10 as GCB manages this.
To save more memory .... Consider that ALL I/0 pins default to inputs on Power up. Therefore, there is no absolute need too explicitly set an I/0 as an input as this is the default POR State. Only the outputs really need to be set with DIR. This can save a few words of memory . You could save even more memory by setting the TRIS Registers directly like this:
TRISA = 0b11011011 ' "1" is Input "0" is output
TRISB = 0b11010000
TRISC = 0b11100111
Then comment out all of the DIR statements
But alas ... if you are scrambling for even more memory, it might be prudent to get the right sized chip for the application, one that gives you some wiggle room.
William
Edited to correct TRIS bits
Last edit: William Roth 2021-09-30
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
and not "XXXX". So I have data coming in, I am scaling it and I want to display it on an GLCD. 10V shows up at 1000, 9.90V shows up as 990V, etc etc. I want it to show up as "10.00V" or "1.024A", etc etc. Normally I know I could convert it to a string, and pad it. But here is the caveat: Im running low on memory. The program barks at me if I try to convert things to a string. Currently I have used up 90-95% of my PICs program and Ive tried to slim things down as much as I can, but the scaling takes up a ton of program space. Now I would be OK with it showing up as is; BUT when the voltage being read back is less than 1000 (or 4 digits) the last digit still stays on screen. A current work around is to basically clear the screen when I turn the encoders. Its lazy but it works.
Ive tried a few things, but most of them have lead to dead ends. So I figured Id ask here. See lines 220 to 226 (The GLCD print commands)
I see the following options:
1) De-solder the PIC and upgrade to the same family but with more memory (I think theres one with 2k program memory).
2) Downgrade to a smaller I2C GLCD .
3) Use a nextion GLCD-but this is slightly pricey. The one advantage this has is that I can also implement an NTC temperature sensor to control the heatsink fan since I will have more room for code. I can also do a lot more with the screen and not have to worry about the PIC being bogged down by sending data to the screen all the time.
4) Make/design a small board to interface to the GLCD I want and just off load the commands to it, and send the commands via UART. I know where I want things, I could just program this PIC to display data. This is more of a coding exercise though.
Non relevant info: The project is an adjustable bench power supply. Ive written my own encoder function based on one I found for arduino. The two encoders adjust the voltage and current limits. Voltage and current is read back to a screen. I havent packed it up yet, but it does work pretty nicely. Next post will have the mostly done schematics.
Thanks for the help-Currently at work so any code changes will have to be done tonight.
Last edit: Chris S 2021-09-27
Your code would be more relevant to you query than the schematic is but, from what you have described, if you are managing to display xxxxV can you not use fixed point and send 2 chr's, point, 2chr's, 'V' ?
You mean convert to string? yes but string ops put my code overboard and it wont compile since I ran out of space
Schematic.
If anyone wants to build this, dont populate the LM334. It remains to be seen if I need that.
Add the ADC OPTIMISER code. This will save 100 words. I am assuming you only need ADC 0 and 1... else edit. See below.
Remove the Version Control variables.
Change the SPI commands in the library to NOT included the software SPI when you are using the hardware SPI....
Would yield... 85.96%
Compiler Version: 0.98.07 2021-08-24 (Windows 64 bit) : Build 1020 Program Memory: 3521/4096 words (85.96%) RAM: 152/512 bytes (29.69%) OSC: INTOSC, 16Mhz (Internal oscillator) Chip: 16F1773
Evan
Gave this a shot, and I still only have room for one Str conversion, 96.53%. I can convert it to a string, but any manipulation (like left padding), and I run out of memory.
ex:
VoltageString=StrInteger(VoltageOutput_Scaled)
GLCDPrintWithSize(0, 10,leftpad(VoltageString,4,"0"),2,TFT_RED )
I have a sinking feeling my options are running out.
Edit: as of 9/27, 7:13PM EST. They have the larger device in production (F1778) which has 28k program space. Might as well go over board right?
Tried Recompiling the program with the chip options
PIC16F1776 or PIC16F1778
and I get an error
"BenchtopPSU20210927AWithGLCD.gcb (185): Error: Variable ADPREF was not explicitly declared"
Using version:
0.98.07 2021-05-27 (Windows 64 bit)
Interesting. Nothing else has changed.
Edit #2 @7:26PM.
Added in the lines
ADPREF,ADCON1,1
ADPREF,ADCON1,0
On line 2624 and 2625 respectively and this fixes it. Compiles with 50% Program space used
1778 Chip compiles as well if I make the same mods :). I think we have the obvious solution, even though its a slight PITA to de-solder an SOIC....that is if I can find the chip :(
Last edit: Chris S 2021-09-27
Try this... This removed the WithSize method but I guessing without the actual program. 92%....
And, I would like to see the ASM.
Sorry for the later response. I had to wait to engineer another project to justify shipping costs on a few PICs. But Now ive upgraded to a 16F1778. This code works perfectly and I have more than enough ram + program memory to do other things with it as well. So I thank you and everyone else for your input.
But now I am on to the next set of problems: The ADC responds too quick and the values change quickly under load even though they stay the same on my meter. When no load is present its fine and reads a perfect 1000mV (10.00V). Under load, it varies from 9700 to 9800. Im guessing its picking up the noise from loading down the rail.
I had this problem once before, and I forgot how I solved it.
Last edit: Chris S 2021-11-18
Good to hear the chip sorted.
The ADC - an ADC Delay to be added?
I think I need a delay, or something else but I suspect a few things:
1) Noise on the 5V rail when loaded (its not the rail being loaded though). I am using a solid voltage reference though. I dont suspect its this but I'll check the 5V rail when the main rail is being loaded anyway.
2) Noise from the output being picked up by the ADC. In this case it would be the 120Hz waveform from the filter caps making it through the pass transistor. I suspect its picking up the peaks and valleys. I'll have to confirm values with my oscilloscope.
3) Quantum mechanics. If I look away it will probably work but observing the circuit collapses its function and the outcome changes 🤣
What Ive implemented so far: Run timer 1 at one second intervals and read the ADC then. Using this method, it still happens. The only slight issue this causes is that I dont see the change on the screen if Im changing the voltage.
For #2 maybe an averaging function would work?
Other possibilities: Maybe heat killed my op-amp again from being near the PIC being desoldered?
Add a small capacitor across the ADC input? Depending on your resistive divider 10nF to 100nF or so? You could solder/connect the capacitor directly across the lower portion of the resistive divider.
Of course averaging consecutive ADC readings would work just as well.
Not forgetting where and how the negative return is connected on the circuit you are measuring the voltage of.
I think I have a clue as to whats going on. Makes no sense but here we are. My voltage reference gets dragged down when a load is placed on the main circuit. Heres the kicker: That voltage reference isnt tied to anything else BUT the PIC micro 😕 😕 😕
I mean, the PIC ADC shouldnt take up much current from the voltage reference. Maybe I'll reduce the resistor value and see if that fixes it. So it doesnt seem to be software. But Im tired.
So, I did de-solder and resolder this reference. Maybe I ruined it?
Regarding the ADPREF error. PICINFO shows that ADPREF does not exist. Which is correct per the MPASM INC file, which shows:
However, this does not match the datasheet
The INC file should be:
The errata does not show this error. We should report.
We can sort in the DAT file generation, but, can you do me a favor - examine all these parts... do they all have the same issue?
We can adapt the generation (so, this is resolved in the future) but I need to know which chips are impacted.
So, I need some analysis to correct for everyone else.
You know whats strange? Notepad++ can usually open files with no problem. It opens the .dat files but for some reason, doesnt show the ADC registers. They show up properly if I open it up in GCCB.
PIC16LF1779-No Ref
PIC16LF1778- No Ref. Shows it but I think I modified it.
PIC16LF1777-No Ref
PIC16LF1776-No Ref
PIC16LF1773-No Ref
PIC16F1779-No ADPREF
PIC16F1778-No Pref (but I know I modified this one last night)
PIC16F1777-No ADPREF
PIC16F1776-Has ADPREF. I possibly modified this one.
PIC16F1773-Has ADPREF
I have one more thing to try before work. I'll open up MBLabX and start a project there with the 1779Last edit: Chris S 2021-09-28
I will add to the generation process a fix to resolve the issue in Great Cow BASIC.
Re MPLAB-X if you are using 5.xx then the compiler does not use the INC files. The way to test... is to select MPASM as the compiler in Great Cow BASIC. And, MPASM cannot parse ADPREF
Also, more importantly. Where you set ADPREF = 10 this is wrong. Very wrong.
This is the correct change
ADPREF is two bits of register ADCON1 therefore you cannot set to 10. If you use the change you used you will simply incorrectly set bits in ADCON1. To be clear ADPREF does not exist as a register or byte. And, should not be created as such. ADPREF0 and ADPREF1 are bits. To set these bits use a ADCON1 mask, an alias, or directly set as follows;
@Chris S "10V shows up at 1000, 9.90V shows up as 990V, etc etc. I want it to show up as "10.00V"
divide number ie 990 by 100 and print
then print "."
then divide 990 by 10 and print
should get 9.99
edit think it need mod
Last edit: stan cartwright 2021-09-29
Looking at the code:
This can be reduced to :
There is no need to set the ADCON1.1 and ADCON1.0 bits twice
There is also no need to Set "ADON = 1" If you are using READAD or READAD10 as GCB manages this.
To save more memory .... Consider that ALL I/0 pins default to inputs on Power up. Therefore, there is no absolute need too explicitly set an I/0 as an input as this is the default POR State. Only the outputs really need to be set with DIR. This can save a few words of memory . You could save even more memory by setting the TRIS Registers directly like this:
Then comment out all of the DIR statements
But alas ... if you are scrambling for even more memory, it might be prudent to get the right sized chip for the application, one that gives you some wiggle room.
William
Edited to correct TRIS bits
Last edit: William Roth 2021-09-30
I made a few more changes/corrections to the original code. Now at 88.45% All of the changes will be remarked with
The compiler now reports:
3623/4096 words (88.45%) RAM: 222/512 bytes (43.36%)
Review the code to see the changes.
@Anobium
Not too sure that the compiler is reporting the correct Program Memory usage.
(4096 - 3623) = 473 Words Free
However looking at the hex ( Using PK2+ Hex View) I see only 424 Words Free
William
Last edit: William Roth 2021-09-30
@williamroth I just loaded into PIC-AS the HEX looks like 471 words. Look ok here using PIC-AS as a reference.
It looks ok but due to how memory "pages" are managed in 16F Chips ...all 471 words may not be available.
Last edit: William Roth 2021-09-30