PDA

View Full Version : 16F877A and LCD HD44780



epilot
- 24th October 2013, 00:52
Good day, Everybody,

I am building a VU meter which uses a 16F877A and HD44780. The link below provides both schematic and code in PicBasic (assembler and HEX are also available via a download). The schematic is straight forward and does not deviate from other examples of 16F877A and HD44780 combos. I ran the PicBasic code provided by the author and compiled my own HEX. Original HEX is also available from the author via a download.
http://www.zaxione.com/in...varias-visualizaciones (http://www.zaxione.com/index.php/8-proyectos/1-vu-meter-estereo-con-varias-visualizaciones)

Unfortunately, the LCD is not initializing properly and I have usual 16 block on the top line problem. I wonder if it is a timing problem or perhaps something is missing in the code. Both 16F877A and HD44780 which I am using are working properly in different projects with different HEXs.

Please let me know what I might be missing here.

Thank you.

Archangel
- 24th October 2013, 11:08
Try add flags = 0
I usually eliminate POT from circuit & tie pin 3 to ground
The PIC 16F877a has power and ground pins on both sides of the chip, make sure both sides are hooked up
I did not see any config statement in that code, so how it is running or not is anyone's guess, are you sure it is? Try making a blinking led to be sure.

The code below is the 16F877A.inc file from my v2.6 install


;************************************************* ***************
;* 16F877A.INC *
;* *
;* By : Leonard Zerman, Jeff Schmoyer *
;* Notice : Copyright (c) 2003 microEngineering Labs, Inc. *
;* All Rights Reserved *
;* Date : 11/06/03 *
;* Version : 2.45 *
;* Notes : *
;************************************************* ***************
NOLIST
ifdef PM_USED
LIST
include 'M16F87xA.INC' ; PM header
device pic16F877A, xt_osc, wdt_on, lvp_off, protect_off
XALL
NOLIST
else
LIST
LIST p = 16F877A, r = dec, w = -302
INCLUDE "P16F877A.INC" ; MPASM Header
__config _XT_OSC & _WDT_ON & _LVP_OFF & _CP_OFF
NOLIST
endif
LIST


Notice it says XT_OSC, this is incorrect for your 20 mhz osc, it should say HS_OSC, for any resonator and crystals above 4 mhz, this is an oscillator power setting, either change it here or comment this line out and put the config in your code. This statement assumes you are using a version older than 3.0

It is always better to copy paste your code than a link to somewhere,however; a link does make a good supplemental.

epilot
- 24th October 2013, 13:02
Thank you for the reply.

To answer your questions - I am using PicBasic Pro 3.0.7 evaluation version and I am running it in MicroCode Studio. I downloaded it because the original program was written in PicBasic. My experience with PicBasic is limited. I am working in assembly most of the time. I powered the PIC on both sides.

I agree with you that the PIC is not configured and this could be the cause of the problem. I contacted the author and asked him if the program and its HEX are complete and functional. He did not reply. His lack of reply strengthen my suspicion that the code is not complete.

Where you lost me is the code you proposed to include. Where does it go? Would you mind posting a complete PicBasic code as you propose to run to eliminate the problem with 16 blocks on the top line. I do not want to create new problems while I am trying to eliminate the old ones.

Thank you.

towlerg
- 24th October 2013, 13:30
Hi epilot,

I tried to download the Proteus sim file but google translate and I were defeated, it seemed to want me to register but wouldn't let me. If you download all the files and include them in a post I'll run Proteus for you. Sorry to lazy to create the Proteus sim from scratch.

George

epilot
- 24th October 2013, 14:39
George,

I did not understand what files do I need to download and include in this post Proteus files or the original files of the VU meter? If you mean the original files of the VU Meter, then what files do I need to post?

Please clarify.

epilot
- 24th October 2013, 16:06
OK, George, I think you meant the original VU meter files. I am attaching a ZIP folder which includes TinyCad, HEX, and PBP files. Please let me know if you need other files posted there.

I think that Proteus will not run a simulation because Archangel identifies the problem - the PIC is not configured and thus does not operate properly. I just do not know how to implement the code he proposed to insert in to the original PicBasic code.

Archangel
- 24th October 2013, 18:26
Try This:


#CONFIG
__config _HS_OSC & _WDT_ON & _CP_OFF & _BOREN_OFF

#ENDCONFIG

epilot
- 24th October 2013, 21:33
Archangel,

Thank you. I added the code you supplied just above the define OSC 20 line and it was enough to initialize the PIC. This is the good news. There are bad news, however.

1. Something is still missing in the code because applying 1 Vpp from a generator to the diodes of the left and right channels activates only 7 blocks out of 16. Applying 1.9 Vpp activates all 16 blocks. In other words, the VU meter is very insensitive and the logarithmic scale (I believe it uses a logarithmic scale) is way off.

2. Something is still missing in the code because the button that is connected to pin 35 of the PIC and which is suppose to change configuration of the bars does not change the configuration of the bars but instead in completely resetting the VU meter starting the sequence again.

Any ideas how to fix this?

Thank you.

towlerg
- 25th October 2013, 00:00
Prog seems to run just fine in sim. See attached GIF's. First one steps thro all the modes and both traces are 2 volts. Second just a few modes and 1.5 volts. Both show 2 and 4 Hz traces. BTW if you don't specify config fuses most compilers will insert defaults ditto xtal. The fuses for this prog (from Proteus) is 0x3FFB.

George

epilot
- 25th October 2013, 03:06
George,

Thank you. This gives some food for thought. Since my VU meter still does not work properly I have several questions.

1. What voltages did you apply to the anodes of the diodes and what voltages were required to engage all 16 blocks of the display in your simulation?
2. What type of diodes did you use?
Is it possible that Proteus introduces some parameters that I cannot obtain on my protoboard and which make all the difference?

My VU meter still does not work properly and:

1. Resets itself every 2 minutes or so.
2. Push button functions as a complete reset and does not change the appearance of the bars.
3. It takes slightly more that 0.1 Volt to activate one bar and it takes about 1.8 Volt to activate all 16 bars.

Archangel
- 25th October 2013, 08:48
_WDT_ON try change to _WDT_OFF it could be your reset

I am NOT overly familiar with the analog stuff. What I THINK I SEE, is ADCON1 is set to use VDD & VSS as voltage reference, you can change this to an external vref for your A/D conversion in the ADCON1 register, see sect. 11.2 of the data sheet, and you can supply that vREF on AN3, also you lose about .7 volt across those diodes, you could use schottkey or germanium which switch at lower voltage.

Acetronics2
- 25th October 2013, 09:22
Hi, Joe

looks most of the config section diseappeared in the source file ...

Where are gone the TRISA/TRISB definitions ??? , that between others !!!

I know most of PBP commands set the I/O's by themselves ... but not all of them !!!
especially IF ... THEN !!!

Have a nice day ...

Alain

PS: here, the sim runs fine ...

Archangel
- 25th October 2013, 10:19
You Shore is RIGHT ! How ya doin' Alain ?
I just sort of think the author of this code expected users to download and not dissect the code, foolishly I filtered it through Google translator, then spent an hour fixing what Google did to it ;) What I learned was the author is worried about audio pulses above 5 volts blowing the pic's inputs and he suggested resistors and zeners to clip those voltages. I am guessing he might have used it on speaker outputs, whereas our member I think wants it on his preamps.

towlerg
- 25th October 2013, 14:16
1. What voltages did you apply to the anodes of the diodes and what voltages were required to engage all 16 blocks of the display in your simulation?
2. What type of diodes did you use?
Is it possible that Proteus introduces some parameters that I cannot obtain on my protoboard and which make all the difference?

1. As I said, 2volts on the first run and 1.5 on the second. 2 and 4 Hz for both.
2. No components were changed.
It's a sim so all things are possible. BUT these are very common devices and Proteus will report wrongly configured i/o. eg. using ADC module with i/o set for digital. I agree that the prog gets no style points and relies upon defaults but it does seem to work. Sims tend to fall down with arcane timing issues (race conditions, read modify write etc.)

With all due deference to the other more PBP savy posters on this thread your problem is most likely physical. Check that you have flashed what you think you have flashed, use the pre-compiled HEX. Check component values and the circuit. Make sure your input is what you think it is.

For example, does your programmer pick up the config fuses from the HEX file? According to my trusty PicKit2 it should be 2F4D.

Good luck, George

epilot
- 25th October 2013, 16:48
Thank you for all replies.

I rebuilt the VU meter on a different protoboard and with _WDT_OFF it runs properly.


This is interpretation of the original code:

Sections labelled "GRAFx" configure the user defined graphics characters of the LCD to give the different VU meter graphical appearance.

Section labelled "BARRA" reads the ADC input, only one for each loop.

Alternating between the 2 ADC inputs, and also between the 2 LCD lines, is controlled with variable "MARCA1".

The value from the ADC is divided by 5 to give a remainder ("RESTO") between 0 and 5 that represent the 5 pixel columns of one LCD character .

The display is printed with a proportional number of full graphical characters, and then a partial character with only the relevant pixel columns depending on the remainder of the ADC reading (RESTO).

After finishing drawing the VU line on the display 3 characters are cleared to erase the remaining of an eventual previous longer line.

Each press of the push-button changes the graphical representation in a sequential fashion controlled by "MARCA2". Depending on this sequence the main program loop is closed via the corresponding "GRAFx" section. Change on the graphical representation is obtained by reconfiguring the user defined characters of the LCD via section labelled "GRAFx".

"cgram" is an area of the LCD internal RAM that is used to store the 8x5 bitmaps (pixels) of user defined characters.


I wonder is it is possible to increase sensitivity of the VU meter (10 times) so it could measure per-amplified signals. Currently it takes 0.1 volt to activate a bar.

Thank you.

towlerg
- 26th October 2013, 01:50
BTW default settings for devices can be found in the relevant *.pbpinc file (in this case PIC16F628A.PBPINC) and the watchdog is indeed enabled by default. If you turn it off do you see a different HEX image from the pre-compiled one?

It will be more sensitive with out the diodes (I quess they are for protection - but what do I know). Thinking aloud - If you double the number that the adc returns does that double the sensitivity? not if its a log scale! Post some code when you get it working the way you want it.

George

epilot
- 26th October 2013, 02:28
1. It will not work without diodes because ADC needs RMS voltage to operate properly and the diodes (shotky works the best) provide the required RMS voltage.

2. Yes WDT_OFF gives a different HEX.

3. The place where the sensitivity could probably be adjusted is here:

' Read ADC input

BARRA:
IF MARCA1 = 1 THEN 'Si es verdadero
LINEA = $2 '1 Linea LCD, muestra canal L
ADCIN 7, CANAL
MARCA1 = 0
ELSE 'Si no lo es
LINEA = $c0 '2 Linea LCD, muestra canal R
ADCIN 6, CANAL
MARCA1 = 1
ENDIF


Again, my knowledge of PicBasic is limited. Since the author does not run a logarithmic scale some of the experts around here could probably say right away how to increase the sensitivity. The author was certainly using this VU meter to measure output signal of a power amplifier (my headphone amplifiers do not fully deflect the scale of this VU meter) and thus purposely "desensitized" the ADC.

towlerg
- 26th October 2013, 14:08
1. It will not work without diodes because ADC needs RMS voltage to operate properly and the diodes (shotky works the best) provide the required RMS voltage.

In that case you've found an error in the sim. Sim show significantly increased "movement" but no other changes.

George

Archangel
- 27th October 2013, 00:25
epilot,
I think you're off base here, A translated portion


BARRA: 'spanish
IF MARCA1 = 1 THEN 'Si es verdadero
LINEA = $2 '1 Linea LCD, muestra canal L
ADCIN 7, CANAL
MARCA1 = 0
ELSE 'Si no lo es
LINEA = $c0 '2 Linea LCD, muestra canal R
ADCIN 6, CANAL
MARCA1 = 1
ENDIF

BAR : 'english
IF Mark1 = 1 THEN ' If true
LINE = $2: ADCIN 7, CHANNEL: Mark1 = 0 ' 1st line LCD shows L channel
ELSE ' If it is not
LINE = $c0: ADCIN 6, CHANNEL: Mark1 = 1 ' 2nd Line LCD shows R channel
ENDIF 'End of the comparison

I am pretty sure sensitivity is as I stated above in post 11, ADCON1 & VREF

epilot
- 27th October 2013, 03:09
Archangel,

Thank you. I read section 11.2. So, I am going to instal a 10K pot and connect its wiper to RA3 to serve as Vref+. I will ground RA2 and to serve as Vref-. The low pin of the pot will be grounded and the top pin will be connected to +5VDC. I will change the line ADCON1 = 00000000 to be ADCON1 = 00001000

Does this make sense?

Archangel
- 27th October 2013, 07:53
That's how I see it, Grant You, I have not tried it, ever. Anyone out here who has please feel free to chime in.

Looks like we will learn together, the difference is . . . I can't smell the smoke :D

Sherbrook
- 27th October 2013, 10:15
Hi epilot
Another way to do it would be to use an op-amp
Google "op-amp precision rectifier full wave"
There are quite a few simple circuits that would do the job. Ordinary diodes can be used, and also you can set the gain of the op-amp to give whatever output voltage you want from your pre-amp
Phil

epilot
- 27th October 2013, 15:42
I installed an LM324 yesterday with a gain of 4 and it did the job, but, it requires 5 parts, whereas what Archangel proposed requires only two - a pot and a capacitor to ground the wiper.

However, it did not work as desired. Perhaps ADCON1 = 00001000 is not what is required, although it seems to be the right code.

What I had was - the low pin of the pot was grounded, the high pin was on +5VDC, wiper was connected to pin 5 (RA2) of the PIC, and pin 4 (RA3) of the PIC was grounded. Rotating wiper clockwise did increase voltage on pin 5 (RA2). Yet, I saw only two lines (not bars) with maximum sensitivity being selected (wiper turned fully clockwise).

What am I missing here?

Now, there is another problem, when I went back to the original program with ADCON1 = 00000000 the VU meter stopped to operate properly. It does initialize and measure volume, but only with one set of bars. The push button again is acting as a complete reset and does not switch appearance of the bars. Perhaps Archangel can suggest something here as it again appear to be configuration problem. Once this is fixed and I am at square one, I will try to implement Archangel proposal with RA2/RA3.

Thank you.

This is the current code:


'************************************************* ******************************
'* Archivo : VUMETER.PBP *
'* Autor : Saúl (Alias Zaxione) *
'* Fecha : 08/11/2009 *
'* Versión : 1.0 *
'* Nota : VU Meter Estéreo con varias visualizaciones. *
'* Web : http://www.zaxione.com *
'************************************************* ******************************
#CONFIG
__config _HS_OSC & _WDT_OFF & _CP_OFF & _BOREN_OFF

#ENDCONFIG
DEFINE OSC 20 'Oscilador de 20 MHz

'************************************************* ******************************
' LCD I/O DEFINITIONS
DEFINE LCD_DREG PORTB 'LCD PORT para envío de datos B
DEFINE LCD_DBIT 4 'LCD utiliza los Bit inferior 0 o superior 4
DEFINE LCD_RSREG PORTB 'LCD RS en el PORTB
DEFINE LCD_RSBIT 0 'LCD RS PORTB.0
DEFINE LCD_EREG PORTB 'LCD E en el PORTB
DEFINE LCD_EBIT 1 'LCD E PORTB.1
DEFINE LCD_BITS 4 'LCD se utilizan 4 o 8 bits para datos
DEFINE LCD_LINES 2 'Numero de lineas del lcd

'************************************************* ******************************
' LCD DEFINITIONS
DEFINE ADC_BITS 8 'Resultado del ADC 8 o 10 bits
DEFINE ADC_CLOCK 3 'Ajuste del reloj
DEFINE ADC_SAMPLEUS 50 'Ajuste del tiempo de muestreo en microsegundos

'************************************************* ******************************
' VARIABLES
CANAL var BYTE 'Nombre de la variable
LINEA VAR BYTE 'Nombre de la variable
CONTADOR VAR BYTE 'Nombre de la variable
RESTO VAR BYTE 'Nombre de la variable
MARCA1 VAR BIT 'Nombre de la variable
MARCA2 var BYTE 'Nombre de la variable
PULSADOR var PORTB.2 'Pulsador en el PORTB.2

'************************************************* ******************************
' PROGRAM
PAUSE 500 'Tiempo necesario para la iniciación del LCD 7
ADCON1 = 00000000 'Definir todos los PORTA y PORTE como analógicos

'************************************************* ******************************
' INITIAL MESSAGE --> "Zaxione"
LCDOUT 254, 64, 1 ,2 ,5, 5 ,5 ,5 ,2 ,1 'cgram posición 0
LCDOUT 254, 72, 24 ,4 ,26, 2 ,2 ,26 ,4 ,24 'cgram posición 1
LCDOUT $FE, 1 'Borrado de la pantalla
' Shift message Left
FOR CONTADOR = 144 TO 130 STEP -1 'Cuenta atras
LCDOUT $FE, CONTADOR, 20, 0, 1, "Zaxione " 'Imprimir en pantalla
PAUSE 150 'Pausa de 0,15 segundos
NEXT CONTADOR 'Regresa a CONTADOR
PAUSE 2000 'Pausa de 2 segundos
' Shift message Right
FOR CONTADOR = 130 TO 144 'Cuenta hacia delante
LCDOUT $FE, CONTADOR, 20, 0, 1, "Zaxione " 'Imprimir en pantalla
PAUSE 150 'Pausa de 0,15 segundos
NEXT CONTADOR 'Regresa a CONTADOR
LCDOUT $FE, 1 'Borrado de la pantalla

'************************************************* ******************************
' VU line style 1 (graphic bitmaps)
GRAF1:
MARCA2 = 1
LCDOUT 254,64, 0 ,16 ,16, 16 ,16 ,16 ,16 ,0 'cgram posición 0
LCDOUT 254,72, 0 ,24 ,24, 24 ,24 ,24 ,24 ,0 'cgram posición 1
LCDOUT 254,80, 0 ,28 ,28, 28 ,28 ,28 ,28 ,0 'cgram posición 2
LCDOUT 254,88, 0 ,30 ,30, 30 ,30 ,30 ,30 ,0 'cgram posición 3
LCDOUT 254,96, 0 ,31 ,31, 31 ,31 ,31 ,31 ,0 'cgram posición 4
PAUSE 300
GOTO BARRA

'************************************************* ******************************
' VU line style 2 (graphic bitmaps)
GRAF2:
MARCA2 = 2
LCDOUT 254,64, 0 ,24 ,24, 24 ,24 ,24 ,24 ,0 'cgram posición 0
LCDOUT 254,72, 0 ,24 ,24, 24 ,24 ,24 ,24 ,0 'cgram posición 1
LCDOUT 254,80, 0 ,27 ,27, 27 ,27 ,27 ,27 ,0 'cgram posición 2
LCDOUT 254,88, 0 ,27 ,27, 27 ,27 ,27 ,27 ,0 'cgram posición 3
LCDOUT 254,96, 0 ,27 ,27, 27 ,27 ,27 ,27 ,0 'cgram posición 4
PAUSE 300
GOTO BARRA

'************************************************* ******************************
' VU line style 3 (graphic bitmaps)
GRAF3:
MARCA2 = 3
LCDOUT 254,64, 0 ,0 ,0, 16 ,16 ,0 ,0 ,0 'cgram posición 0
LCDOUT 254,72, 0 ,0 ,0, 24 ,24 ,0 ,0 ,0 'cgram posición 1
LCDOUT 254,80, 0 ,0 ,0, 28 ,28 ,0 ,0 ,0 'cgram posición 2
LCDOUT 254,88, 0 ,0 ,0, 30 ,30 ,0 ,0 ,0 'cgram posición 3
LCDOUT 254,96, 0 ,0 ,0, 31 ,31 ,0 ,0 ,0 'cgram posición 4
PAUSE 300
GOTO BARRA

'************************************************* ******************************
' VU Line style 4 (graphic bitmaps)

GRAF4:
MARCA2 = 4
LCDOUT 254,64, 0 ,16 ,16, 16 ,16 ,16 ,16 ,0 'cgram posición 0
LCDOUT 254,72, 0 ,16 ,16, 16 ,16 ,16 ,16 ,0 'cgram posición 1
LCDOUT 254,80, 0 ,20 ,20, 20 ,20 ,20 ,20 ,0 'cgram posición 2
LCDOUT 254,88, 0 ,20 ,20, 20 ,20 ,20 ,20 ,0 'cgram posición 3
LCDOUT 254,96, 0 ,21 ,21, 21 ,21 ,21 ,21 ,0 'cgram posición 4
PAUSE 300
GOTO BARRA

'************************************************* ******************************
' VU Line style 5 (graphic bitmaps)
GRAF5:
MARCA2 = 5
LCDOUT 254,64, 0 ,0 ,0, 4 ,0 ,0 ,0 ,0 'cgram posición 0
LCDOUT 254,72, 0 ,0 ,4, 14 ,4 ,0 ,0 ,0 'cgram posición 1
LCDOUT 254,80, 0 ,0 ,14, 14 ,14 ,0 ,0 ,0 'cgram posición 2
LCDOUT 254,88, 0 ,4 ,14, 31 ,14 ,4 ,0 ,0 'cgram posición 3
LCDOUT 254,96, 0 ,14 ,31, 31 ,31 ,14 ,0 ,0 'cgram posición 4
PAUSE 300
GOTO BARRA

'************************************************* ******************************
' VU Line style 5 (graphic bitmaps)
GRAF6:
MARCA2 = 6
LCDOUT 254,64, 0 ,14 ,31, 31 ,31 ,14 ,0 ,0 'cgram posición 0
LCDOUT 254,72, 0 ,14 ,31, 31 ,31 ,14 ,0 ,0 'cgram posición 1
LCDOUT 254,80, 0 ,14 ,31, 31 ,31 ,14 ,0 ,0 'cgram posición 2
LCDOUT 254,88, 0 ,14 ,31, 31 ,31 ,14 ,0 ,0 'cgram posición 3
LCDOUT 254,96, 0 ,0 ,0, 31 ,0 ,0 ,0 ,0 'cgram posición 4
PAUSE 300

'************************************************* ******************************
' Read ADC input
BARRA:
IF MARCA1 = 1 THEN 'Si es verdadero
LINEA = $2 '1ºLinea LCD, muestra canal L
ADCIN 7, CANAL
MARCA1 = 0
ELSE 'Si no lo es
LINEA = $c0 '2ºLinea LCD, muestra canal R
ADCIN 6, CANAL
MARCA1 = 1
ENDIF 'Fin de la comparación

'************************************************* ******************************
' Remainder of DIV5 --> nro of pixels columns of last char in VU graph
RESTO = (CANAL // 5) 'Operación restó de la división
LCDOUT $FE, LINEA 'Inicia la escritura en el LCD
FOR CONTADOR = 1 TO (CANAL / 5) 'Cuenta hacia delante
LCDOUT 4 'Imprime cgram posición 4
NEXT CONTADOR 'Regresa a CONTADOR

' Select last character in VU graph depending on the remainder value
IF RESTO = 1 THEN LCDOUT 0 'Imprime cgram posición 0
IF RESTO = 2 THEN LCDOUT 1 'Imprime cgram posición 1
IF RESTO = 3 THEN LCDOUT 2 'Imprime cgram posición 2
IF RESTO = 4 THEN LCDOUT 3 'Imprime cgram posición 3
' ??? Erase 3 full chars after VU indicator
LCDOUT 20, 20, 20 'Borrado de 3 caracteres

'************************************************* ******************************
' Select graphic style (progress with push-button presses
IF (PULSADOR = 1) and (MARCA2 = 6) THEN GRAF1 '1º Visualización
IF (PULSADOR = 1) and (MARCA2 = 1) THEN GRAF2 '2º Visualización
IF (PULSADOR = 1) and (MARCA2 = 2) THEN GRAF3 '3º Visualización
IF (PULSADOR = 1) and (MARCA2 = 3) THEN GRAF4 '4º Visualización
IF (PULSADOR = 1) and (MARCA2 = 4) THEN GRAF5 '5º Visualización
IF (PULSADOR = 1) and (MARCA2 = 5) THEN GRAF6 '6º Visualización

'************************************************* ******************************
GOTO BARRA
END

epilot
- 27th October 2013, 17:30
OK, a fixed the problem of the push button acting as a complete reset by adding _LVP_OFF. The damn thing is capricious and unpredictable as weather in May.

Now, I am back to section 11.2 to implement Archangel's proposal. Maybe it will work on a second run with _LVP_OFF.

epilot
- 27th October 2013, 22:38
Thus far reading section 11.2, I could not understand what is wrong and why the RA3/RA2 arrangement via pot does not work.

To keep options open I was playing with LM324 arrangement. One issue I cannot figure out. With LM324 inline with the VU meter, without any signal being supplied to the LM324, I have 16 blocks on the top and bottom lines of the display. Once any signal is applied to the LM324, the blocks disappear and the VU meter operates as designed.

The sensitivity of the VU meter with LM324 is 300 mV full deflection of the VU meter scale on frequency of 1 KHz, or about 30mV per each block of the display.

towlerg
- 28th October 2013, 00:13
Hi epilot,

you piqued my curiosity re. using vref to offset the ADC. Its limited by the requirment that Vref+ min is 2volts. Using a voltage divider 10k to gnd and 15k to Vdd (5volts). Pin 5 (AN3) goes to the divider. The only software change is to add ADCON1 = %00000001 after ADCON0 is set (note the missing binary sign - by shear luck in this case it works without the %) That gets you 2.5 gain - if my maths is right, which would be unusual because I'm rubbish at maths.

The other way to get more gain is to multiply CANAL by some constant


BARRA:
IF MARCA1 = 1 THEN 'Si es verdadero
LINEA = $2
ADCIN 7, CANAL
CANAL = CANAL * 4
MARCA1 = 0 '1ºLinea LCD, muestra canal L
ELSE 'Si no lo es
LINEA = $c0
ADCIN 6, CANAL
CANAL = CANAL * 4
MARCA1 = 1 '2ºLinea LCD, muestra canal R
ENDIF

Now you can adjust the gain on the fly by detecting when it clips and changing constant to a variable. I think I may have suggested in an earlier post that you should divide the ADC output, D'oh (spelling according to Wiki). I think you'll still need some gain on the input.

Hey, I just realised, the ADC in a 877a is 10 bits but CANAL is only a byte, it's throwing away 2 msb's.

George


George

epilot
- 28th October 2013, 01:29
Gerge,

Thank you.

As far as your suggestion to modify the ADCON1 goes, I did not understand how the code should look like. Perhaps you could post the entire program with your modifications so I can compile it to a HEX.

As far as the code which you posted goes, I implemented it in to the original program and compiled it to a HEX. VU meter refused to work with those modifications.

towlerg
- 28th October 2013, 02:25
'************************************************* ******************************
'* Archivo : VUMETER.PBP *
'* Autor : Saúl (Alias Zaxione) *
'* Fecha : 08/11/2009 *
'* Versión : 1.0 *
'* Nota : VuMeter Estéreo con varias visualizaciones. *
'* Web : http://www.zaxione.com *
'************************************************* ******************************
DEFINE OSC 20 'Oscilador de 20 MHz
'************************************************* ******************************
ADCON0 = %00000000 'Definir todos los PORTA y PORTE como analógicos
ADCON1 = %00000001 'Definir todos los PORTA y PORTE como analógicos
PAUSE 500 'Tiempo necesario para la iniciación del LCD
DEFINE LCD_DREG PORTB 'LCD PORT para envío de datos B
DEFINE LCD_DBIT 4 'LCD utiliza los Bit inferior 0 o superior 4
DEFINE LCD_RSREG PORTB 'LCD RS en el PORTB
DEFINE LCD_RSBIT 0 'LCD RS PORTB.0
DEFINE LCD_EREG PORTB 'LCD E en el PORTB
DEFINE LCD_EBIT 1 'LCD E PORTB.1
DEFINE LCD_BITS 4 'LCD se utilizan 4 o 8 bits para datos
DEFINE LCD_LINES 2 'Numero de lineas del lcd
'************************************************* ******************************
DEFINE ADC_BITS 8 'Resultado del ADC 8 o 10 bits
DEFINE ADC_CLOCK 3 'Ajuste del reloj
DEFINE ADC_SAMPLEUS 50 'Ajuste del tiempo de muestreo en microsegundos
'************************************************* ******************************
CANAL var byte 'Nombre de la variable
LINEA VAR BYTE 'Nombre de la variable
CONTADOR VAR BYTE 'Nombre de la variable
RESTO VAR BYTE 'Nombre de la variable
MARCA1 VAR BIT 'Nombre de la variable
MARCA2 var byte 'Nombre de la variable
PULSADOR var PORTB.2 'Pulsador en el PORTB.2
'************************************************* ******************************
LCDOUT 254, 64, 1 ,2 ,5, 5 ,5 ,5 ,2 ,1 'cgram posición 0
LCDOUT 254, 72, 24 ,4 ,26, 2 ,2 ,26 ,4 ,24 'cgram posición 1
LCDOUT $FE, 1 'Borrado de la pantalla
FOR CONTADOR = 144 TO 130 STEP -1 'Cuenta atras
LCDOUT $FE, CONTADOR, 20, 0, 1, "Zaxione " 'Imprimir en pantalla
PAUSE 150 'Pausa de 0,15 segundos
NEXT CONTADOR 'Regresa a CONTADOR
PAUSE 2000 'Pausa de 2 segundos
FOR CONTADOR = 130 TO 144 'Cuenta hacia delante
LCDOUT $FE, CONTADOR, 20, 0, 1, "Zaxione " 'Imprimir en pantalla
PAUSE 150 'Pausa de 0,15 segundos
NEXT CONTADOR 'Regresa a CONTADOR
LCDOUT $FE, 1 'Borrado de la pantalla
'************************************************* ******************************
GRAF1:
MARCA2 = 1
lcdout 254,64, 0 ,16 ,16, 16 ,16 ,16 ,16 ,0 'cgram posición 0
lcdout 254,72, 0 ,24 ,24, 24 ,24 ,24 ,24 ,0 'cgram posición 1
lcdout 254,80, 0 ,28 ,28, 28 ,28 ,28 ,28 ,0 'cgram posición 2
lcdout 254,88, 0 ,30 ,30, 30 ,30 ,30 ,30 ,0 'cgram posición 3
lcdout 254,96, 0 ,31 ,31, 31 ,31 ,31 ,31 ,0 'cgram posición 4
pause 300
goto barrA
'************************************************* ******************************
GRAF2:
MARCA2 = 2
lcdout 254,64, 0 ,24 ,24, 24 ,24 ,24 ,24 ,0 'cgram posición 0
lcdout 254,72, 0 ,24 ,24, 24 ,24 ,24 ,24 ,0 'cgram posición 1
lcdout 254,80, 0 ,27 ,27, 27 ,27 ,27 ,27 ,0 'cgram posición 2
lcdout 254,88, 0 ,27 ,27, 27 ,27 ,27 ,27 ,0 'cgram posición 3
lcdout 254,96, 0 ,27 ,27, 27 ,27 ,27 ,27 ,0 'cgram posición 4
pause 300
goto BARRA
'************************************************* ******************************
GRAF3:
MARCA2 = 3
lcdout 254,64, 0 ,0 ,0, 16 ,16 ,0 ,0 ,0 'cgram posición 0
lcdout 254,72, 0 ,0 ,0, 24 ,24 ,0 ,0 ,0 'cgram posición 1
lcdout 254,80, 0 ,0 ,0, 28 ,28 ,0 ,0 ,0 'cgram posición 2
lcdout 254,88, 0 ,0 ,0, 30 ,30 ,0 ,0 ,0 'cgram posición 3
lcdout 254,96, 0 ,0 ,0, 31 ,31 ,0 ,0 ,0 'cgram posición 4
pause 300
goto BARRA
'************************************************* ******************************
GRAF4:
MARCA2 = 4
lcdout 254,64, 0 ,16 ,16, 16 ,16 ,16 ,16 ,0 'cgram posición 0
lcdout 254,72, 0 ,16 ,16, 16 ,16 ,16 ,16 ,0 'cgram posición 1
lcdout 254,80, 0 ,20 ,20, 20 ,20 ,20 ,20 ,0 'cgram posición 2
lcdout 254,88, 0 ,20 ,20, 20 ,20 ,20 ,20 ,0 'cgram posición 3
lcdout 254,96, 0 ,21 ,21, 21 ,21 ,21 ,21 ,0 'cgram posición 4
pause 300
GOTO BARRA
'************************************************* ******************************
GRAF5:
MARCA2 = 5
lcdout 254,64, 0 ,0 ,0, 4 ,0 ,0 ,0 ,0 'cgram posición 0
lcdout 254,72, 0 ,0 ,4, 14 ,4 ,0 ,0 ,0 'cgram posición 1
lcdout 254,80, 0 ,0 ,14, 14 ,14 ,0 ,0 ,0 'cgram posición 2
lcdout 254,88, 0 ,4 ,14, 31 ,14 ,4 ,0 ,0 'cgram posición 3
lcdout 254,96, 0 ,14 ,31, 31 ,31 ,14 ,0 ,0 'cgram posición 4
pause 300
GOTO BARRA
'************************************************* ******************************
GRAF6:
MARCA2 = 6
lcdout 254,64, 0 ,14 ,31, 31 ,31 ,14 ,0 ,0 'cgram posición 0
lcdout 254,72, 0 ,14 ,31, 31 ,31 ,14 ,0 ,0 'cgram posición 1
lcdout 254,80, 0 ,14 ,31, 31 ,31 ,14 ,0 ,0 'cgram posición 2
lcdout 254,88, 0 ,14 ,31, 31 ,31 ,14 ,0 ,0 'cgram posición 3
lcdout 254,96, 0 ,0 ,0, 31 ,0 ,0 ,0 ,0 'cgram posición 4
pause 300
'************************************************* ******************************
BARRA:
IF MARCA1 = 1 THEN 'Si es verdadero
LINEA = $2
ADCIN 7, CANAL
CANAL = CANAL * 4
MARCA1 = 0 '1ºLinea LCD, muestra canal L
ELSE 'Si no lo es
LINEA = $c0
ADCIN 6, CANAL
CANAL = CANAL * 4
MARCA1 = 1 '2ºLinea LCD, muestra canal R
ENDIF 'Fin de la comparación
'************************************************* ******************************
RESTO = (CANAL // 5) 'Operación restó de la división
LCDOUT $FE, LINEA 'Inicia la escritura en el LCD
FOR CONTADOR = 1 TO (CANAL / 5) 'Cuenta hacia delante
LCDOUT 4 'Imprime cgram posición 4
NEXT CONTADOR 'Regresa a CONTADOR
IF RESTO = 1 THEN LCDOUT 0 'Imprime cgram posición 0
IF RESTO = 2 THEN LCDOUT 1 'Imprime cgram posición 1
IF RESTO = 3 THEN LCDOUT 2 'Imprime cgram posición 2
IF RESTO = 4 THEN LCDOUT 3 'Imprime cgram posición 3
LCDOUT 20, 20, 20 'Borrado de 3 caracteres
'************************************************* ******************************
IF (PULSADOR = 1) and (MARCA2 = 6) THEN GRAF1 '1º Visualización
IF (PULSADOR = 1) and (MARCA2 = 1) THEN GRAF2 '2º Visualización
IF (PULSADOR = 1) and (MARCA2 = 2) THEN GRAF3 '3º Visualización
IF (PULSADOR = 1) and (MARCA2 = 3) THEN GRAF4 '4º Visualización
IF (PULSADOR = 1) and (MARCA2 = 4) THEN GRAF5 '5º Visualización
IF (PULSADOR = 1) and (MARCA2 = 5) THEN GRAF6 '6º Visualización
'************************************************* ******************************
GOTO BARRA
END

changes

1. added "ADCON1 = %00000001"
2. added "CANAL = CANAL * 4" in two places

you could also use 10 bit mode


7116
George

epilot
- 28th October 2013, 02:34
George:

These two lines


ADCON0 = %00000000 'Definir todos los PORTA y PORTE como analógicos
ADCON1 = %00000001 'Definir todos los PORTA y PORTE como analógicos

are giving syntax errors during compilation. Apparently symbol % is not allowed.

towlerg
- 28th October 2013, 03:00
see pbp help under Numeric Constants


PICBasic allows numeric constants to be defined in the three bases: decimal, binary and hexadecimal. Binary values are defined using the prefix '%' and hexadecimal values using the prefix '$'. Decimal values are the default and require no prefix.

Example

100 ' Decimal value 100
%100 ' Binary value for decimal 4
$100 ' Hexadecimal value for decimal 256



in this particular case 0 and 1 binary are the same as 0 and 1 decimal - so delete the percent sign. you need to find out why this is happening. Problem with cut and paste maybe?

I'm running v3.0.7.1

epilot
- 28th October 2013, 03:58
Thank you George,

My mistake - I tried to compile for a wrong PIC, not a 16F877.

On a second run it compiled properly. The PIC does initialize and the "Zaxione" message comes to the display. After that point the VU meter refuses to show coherent information, it shows some nonsense. I will give it another try tomorrow and will report my results.

Thank you again.

towlerg
- 28th October 2013, 13:07
try playing with vref and modifing CANAL separately.

George

epilot
- 29th October 2013, 01:11
George,

Unfortunately, my experimenting did not work out. Do you have any other recommendations?

towlerg
- 29th October 2013, 12:07
Either Front end gain - preamp.

or abandon this code and get googling - i'm sure there are tons of other examples.

George

Archangel
- 30th October 2013, 01:29
Here is Zax.. code translated to English so you can read his comments, it may be useful to you.




#CONFIG
__config _HS_OSC & _WDT_OFF & _CP_OFF & _BOREN_OFF

#ENDCONFIG
;initiation
;Stereo VU Meter with multiple displays .

;For many years the meters needle based analog phones, have been the instruments most commonly used to measure audio levels .
;Today , most computers use LED or LCD displays to indicate the sound level on the other hand , give a colorful and dramatic appearance .
;This project consists of six forms graphically display the stereo audio signal coming through two analog inputs Pic .
;It has multiple applications , as it could be an audio level indicator , liquid level control , voltage or ampere meter in a power supply , temperature indicator , measuring an RF signal , etc ...
;Outline and electronic components :
;For this project we used a 16F877A PIC microcontroller and LCD HD44780 alphanumeric OLED - ORGANIC 2 rows of 16 characters each. Each character has a 5x8 pixel matrix .

;ATTENTION ! Audio peaks above 5 volts can destroy the PIC , to leave a safety margin or add a zener diode and a resistor to limit .
;Project Description:
;First sliding from right to left appears on the display one copyright logo occupying two characters and my Alias " Zaxione " stop in the middle of the screen and waiting two seconds remaining .
;Then moves in the opposite direction as disappears , begins to indicate the level you are getting for the two analog ports Pic .
;Every time we give you a high -level pulse on the PIC PORTB.2 , changes among the six types of visualization.
;The source code :
;It is written in Basic language , namely the PicBasic Pro 2.50C (PBP ) .

' ************************************************** *****************************
'* File: VUMETER.PBP *
' * Author : Saul (Alias Zaxione ) *
'* Date: 08/11/2009 *
'* Version: 1.0 *
'* Note : Stereo VU Meter with multiple displays . *
'* Web : http://www.zaxione.com *
' ************************************************** *****************************
DEFINE OSC 20 ' Oscillator 20 MHz
' ************************************************** *****************************
ADCON1 = 00000000 ' Set all PORTA and PORTE as analog
PAUSE 500 ' Time to initiation of the LCD
DEFINE LCD_DREG PORTB ' LCD data PORT B ships
DEFINE LCD_DBIT 4 ' LCD uses less than 0 or greater Bit 4
DEFINE LCD_RSREG PORTB ' LCD RS in the PORTB
DEFINE LCD_RSBIT 0 ' LCD RS PORTB.0
DEFINE LCD_EREG PORTB ' LCD E in the PORTB
DEFINE LCD_EBIT 1 ' LCD E PORTB.1
DEFINE LCD_BITS 4 ' LCD using 4 or 8 bits for data
DEFINE LCD_LINES 2 ' Number of lines lcd
' ************************************************** *****************************
DEFINE ADC_BITS 8 ' Result of 8 or 10-bit ADC
DEFINE ADC_CLOCK 3 ' Set clock
DEFINE ADC_SAMPLEUS 50 ' Set sampling time in microseconds
' ************************************************** *****************************
CHANNEL var BYTE ' Variable name
LINE VAR BYTE ' Variable name
COUNTER VAR BYTE ' Variable name
REST VAR BYTE ' Variable name
Mark1 VAR BIT ' Variable name
Mark2 var BYTE ' Variable name
pushbutton Var PORTB.2 ' button in the PORTB.2
TRISA = %11111111
TRISB = %00000100
TRISC = %00000000



' ************************************************** *****************************
LCDOUT 254,64,1,2,5,5,5,5,2,1 ' position CGRAM 0
LCDOUT 254,72,24,4,26,2,2,26,4,24 ' 1 position CGRAM
LCDOUT $FE,1 ' Clear screen
FOR COUNTER = 144 TO 130 STEP -1 ' Countdown
LCDOUT $FE , COUNTER , 20, 0 , 1," Zaxione " ' Print Screen
PAUSE 150 ' Pause 0.15 seconds
NEXT COUNTER ' Returns to COUNTER
PAUSE 2000 ' Pause for 2 seconds
FOR COUNTER = 130 TO 144 ' Count forward
LCDOUT $FE,COUNTER,20,0,1," Zaxione " ' Print Screen
PAUSE 150 ' Pause 0.15 seconds
NEXT COUNTER ' Returns to COUNTER
LCDOUT $FE,1 ' Clear screen
' ************************************************** *****************************
GRAF1 :
Mark2 = 1
LCDOUT 254,64 , 0, 16, 16 , 16, 16 , 16, 16 , 0 ' 0 position CGRAM
LCDOUT 254,72 , 0, 24, 24 , 24, 24, 24 , 24, 0 ' 1 position CGRAM
LCDOUT 254,80 , 0, 28, 28 , 28, 28, 28 , 28, 0 ' CGRAM Position 2
LCDOUT 254,88 , 0, 30, 30 , 30, 30, 30 , 30, 0 ' 3 position CGRAM
LCDOUT 254,96 , 0, 31, 31 , 31, 31, 31 , 31, 0 ' 4 position CGRAM
PAUSE 300
GOTO BAR
' ************************************************** *****************************
GRAF2 :
Mark2 = 2
LCDOUT 254,64 , 0, 24, 24 , 24, 24, 24 , 24, 0 ' 0 position CGRAM
LCDOUT 254,72 , 0, 24, 24 , 24, 24, 24 , 24, 0 ' 1 position CGRAM
LCDOUT 254,80 , 0, 27, 27 , 27, 27, 27 , 27, 0 ' CGRAM Position 2
LCDOUT 254,88 , 0, 27, 27 , 27, 27, 27 , 27, 0 ' 3 position CGRAM
LCDOUT 254,96 , 0, 27, 27 , 27, 27, 27 , 27, 0 ' 4 position CGRAM
PAUSE 300
GOTO BAR
' ************************************************** *****************************
GRAF3 :
Mark2 = 3
LCDOUT 254,64 , 0, 0 , 0, 16, 16 , 0, 0 , 0 ' 0 position CGRAM
LCDOUT 254,72 , 0, 0 , 0, 24, 24 , 0, 0 , 0 ' 1 position CGRAM
LCDOUT 254,80 , 0, 0 , 0, 28, 28 , 0, 0 , 0 ' 2 Position CGRAM
LCDOUT 254,88 , 0, 0 , 0, 30, 30 , 0, 0 , 0 ' 3 position CGRAM
LCDOUT 254,96 , 0, 0 , 0, 31, 31 , 0, 0 , 0 ' 4 position CGRAM
PAUSE 300
GOTO BAR
' ************************************************** *****************************
GRAF4 :
Mark2 = 4
LCDOUT 254,64 , 0, 16, 16 , 16, 16 , 16, 16 , 0 ' 0 position CGRAM
LCDOUT 254,72 , 0, 16, 16 , 16, 16 , 16, 16 , 0 ' 1 position CGRAM
LCDOUT 254,80 , 0, 20, 20, 20 , 20, 20 , 20, 0 ' 2 Position CGRAM
LCDOUT 254,88 , 0, 20, 20, 20 , 20, 20 , 20, 0 ' 3 position CGRAM
LCDOUT 254,96 , 0, 21, 21 , 21, 21, 21 , 21, 0 ' 4 position CGRAM
PAUSE 300
GOTO BAR
' ************************************************** *****************************
GRAF5 :
Mark2 = 5
LCDOUT 254,64 , 0, 0 , 0, 4 , 0, 0 , 0, 0 ' 0 position CGRAM
LCDOUT 254,72 , 0, 0 , 4, 14 , 4, 0 , 0, 0 ' 1 Position CGRAM
LCDOUT 254,80 , 0, 0 , 14, 14 , 14, 0, 0, 0 ' 2 Position CGRAM
LCDOUT 254,88 , 0, 4 , 14, 31 , 14, 4, 0, 0 ' 3 position CGRAM
LCDOUT 254,96 , 0, 14, 31, 31, 31 , 14, 0, 0 ' 4 position CGRAM
PAUSE 300
GOTO BAR
' ************************************************** *****************************
GRAF6 :
Mark2 = 6
LCDOUT 254,64,0,14,31,31,31,14,0,0 ' 0 position CGRAM
LCDOUT 254,72,0,14,31,31,31,14,0,0 ' 1 position CGRAM
LCDOUT 254,80,0,14,31,31,31,14,0,0 ' 2 Position CGRAM
LCDOUT 254,88,0,14,31,31,31,14,0,0 ' 3 position CGRAM
LCDOUT 254,96,0,0,0,31,0,0,0,0 ' 4 position CGRAM
PAUSE 300
' ************************************************** *****************************
BAR :
IF Mark1 = 1 THEN ' If true
LINE = $2: ADCIN 7, CHANNEL: Mark1 = 0 ' 1st line LCD shows L channel
ELSE ' If it is not
LINE = $c0: ADCIN 6, CHANNEL: Mark1 = 1 ' 2nd Line LCD shows R channel
ENDIF 'End of the comparison
' ************************************************** *****************************
REST = ( CHANNEL // 5 ) ' Operation subtracted from the division
LCDOUT $FE,LINE ' Start writing in the LCD
FOR COUNTER = 1 TO(CHANNEL/5) 'Count forward
LCDOUT 4 ' 4 position CGRAM Print
NEXT COUNTER ' Returns to COUNTER
IF REST = 1 THEN LCDOUT 0 ' Print CGRAM position 0
IF REST = 2 THEN LCDOUT 1 ' Print CGRAM Position 1
IF REST = 3 THEN LCDOUT 2 ' Prints 2 position CGRAM
IF REST = 4 THEN LCDOUT 3 ' 3 position CGRAM Print
LCDOUT 20, 20 , 20 ' Clearing 3 characters
' ************************************************** *****************************
IF (pushbutton = 1) and (Mark2 = 6) THEN GRAF1 '1 ° Viewing
IF (pushbutton = 1) and (Mark2 = 1) THEN GRAF2 '2 ° Viewing
IF (pushbutton = 1) and (Mark2 = 2) THEN GRAF3 '3 ° Viewing
IF (pushbutton = 1) and (Mark2 = 3) THEN GRAF4 '4 ° Viewing
IF (pushbutton = 1) and (Mark2 = 4) THEN GRAF5 '5 ° Viewing
IF (pushbutton = 1) and (Mark2 = 5) THEN GRAF6 '6 ° Viewing
' ************************************************** *****************************
GOTO BAR
END
;Video of the project in operation:
;In the Downloads area you can find the following files :

; * VUMETER.GIF Circuit Schematic .
; * VUMETER.DSN Scheme for Proteus simulation .
; * VUMETER.PBP Source Code for the PicBasic Pro Compiler ( 2.50C ) .
; * VUMETER.ASM code written in Assembly Language .
; * Language Firmware VUMETER.HEX machine.

;For more information see or expose your questions in the forum " Stereo VU Meter with multiple displays " .

I hope I did not introduce new errors

epilot
- 31st October 2013, 16:20
Thank you, Archangel. I missed your post as I thought that the thread went dead.

Do you have an idea how we can introduce a peak hold for 500 ms or so ?

Thank you.

Archangel
- 1st November 2013, 04:43
Thank you, Archangel. I missed your post as I thought that the thread went dead.

Do you have an idea how we can introduce a peak hold for 500 ms or so ?

Thank you.Honesty I am not sure I even understand the question, read the ADC_SAMPLEUS explanation, it may be what you seek, I think putting caps. on the preamp outputs will lower the impedance too much, unless you buffer with an OP-AMP ?

epilot
- 1st November 2013, 13:44
What I meant was how can we introduce (software wise) a peak signal hold for 500 ms whereas a bar that depicts peak of the signal holds for 500 ms and than falls down.

Example https://www.youtube.com/watch?v=PtTWYq5T62E

Archangel
- 1st November 2013, 18:17
you might look at MAX & MIN in your manual. You will have to create a bit of code to accomplish that probably save the highest adcin val in a separate variable and make additions in your display loops to show it.