Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

LCD displays jitter on last digits

Status
Not open for further replies.

Adri67

Junior Member level 2
Joined
Aug 11, 2014
Messages
24
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
267
I am building a PV (PWM) charge controller with 16x02 LCD (with 74HC595)(3-wire mode) to display the details (volts, amps, etc) to 2 decimal places. The problem I have is that the last 1 or 2 digits jitter too much (from the PWM, noisy load on output, e.g. inverter).
I tried various methods to smooth the DC values before the Arduino PromMini ADC inputs without real success.
Comparing values to my Fluke 17B I saw the clue : instead I should perhaps rather 'sample & hold' the values and let the display update slower at (say) 5x/second.
The question is how to control the '595 (SER, RCLK, SRCLK) to display without updating for say, 200mS.

Is there a different/better method to do this?

Thanks in advance,
Adri67
 

The question is how to control the '595 (SER, RCLK, SRCLK) to display without updating for say, 200mS.

Display update rate has nothing to do with the hardware interface operation. It's a matter of data processing. To get smooth display, you'll either operate an integrating ADC at low speed or average multiple measurement for one displayed value. Update the display only if a new value is available.
 

I'm using Kalman's filter. I gave the code on this forum. Try to search yourself.
 

Perhaps another way of looking at the problem.
If no updated data is allowed to pass from the '595 to LCD's HD44780 for a period (say 200mS) would that not 'freeze' the value displayed?
How would I do that, if it works?
I'm just looking for alternative solutions.
 

Hi,

updating a display more than 3 times per second makes no sense. One simply can not read and understand the full information fast enough.

Filtering of the analog data definitely makes sense. But filtering also means you need a fixed known sample rate. I recommend to use a hardware periferal (timer, counter, interrupts, waverom generation, pwm generation, clock divider...)
Knowing your analog signal is essential if you want stable and reliable readings.

Example: if you have a rectified 50Hz sine signal and filter it with an 0.1s tau RC, then the ripple is still 1.6% of the peak voltage.
(230V RMS --> 325V peak --> 5V ripple). The display value range is 225...230V.
The last digit changes by 5 counts.
If your display resolution is 0.1V, then it changes 50 counts from 225.0...230.0V
Therefore I recommend to take a fixed number of ADC values within integer multiples of 10ms...maybe for exactely 400ms then average the value and display it.
The 400ms generate a display update rate of 2.5 times per second.

For Dc values a tau of 100ms is a good start. See if this works for you.

****
How to update the display only every 200ms?
(I wonder how you do it now...)
One example with 400ms is given above.

Now an example with exactely 1000Hz sample rate.
(each sample takes exactely 1ms. to get 200ms you just need a counter to count from 0 to 199. Every time when it is at 199, then reset the counter to 0, calculate the display value and update the display)
Best and reliable is to use an 1ms interrupt. Within the ISR just handle the AD conversion, add the values up for averaging, increment the counter, check if 199, reset counter and set a flag for the main loop to do the display update. The ISR should not last longer than 100us. No delay() within an ISR)

Now often I read the sentence: "I´ve never used interrupts". --> then learn to use it. Sooner or later you have to. And once you have used it you don´t want to miss it..

Klaus
 

I have tried another solution which reduces the display to about twice per second.
Looking at 74x595 specsheet (Table 1. Function Table) when RCLCK goes high (and SER, SRCLCK, SRCLR and OE are all X [don't care] ), the function is quoted as "Shift register data is stored in the storage register". I then created an oscillator with adjustable mark-space to "gate" the RCLCK feeding the '595.
Now using diodes and resistors I got this working perfectly with display changing about twice per second.
The problem now is to replace the gate hardware with software.

Code:
#include <LiquidCrystal595.h>

const int ledPin = 13 ;
int ledState = LOW ;
long previousMillis = 0 ;
long timA = 500 ;
long timB = 400 ;
int  RCLCK = 6 ;
int  CLCK  = 12;
int  CLCKState = LOW ;
int valX = 0 ;
int valY = 0 ;


// number of analog samples per channel
#define SAMPLES 30

// ADC reference voltage / calibration value
#define V_REF    4.991

LiquidCrystal595 lcd (7, 6, 9);  // change back to 7, 8, 9 later


int sum[4] = {0};                // sums of samples taken
unsigned char sample_count = 0;  // current sample number
float voltage[4] = {0.0};        // calculated voltages
char l_cnt = 0;                  // used in 'for' loops

void setup()
{
  pinMode  (ledPin,  OUTPUT) ;
  pinMode  (CLCK, OUTPUT) ;
  pinMode  (RCLCK,  OUTPUT) ;
  
  
    lcd.begin  (20, 4);
    
  TCCR2A = TCCR2A | 0x30;
  TCCR2B = TCCR2B & 0xF8 | 0x01;
  analogWrite(11, 110);
  analogWrite(3, 130);   
}

const int setPoint = 660.0;
int measurement = 0;
int pulseWidth = 0;
int difference = 0;
int stepSize = 0;

void loop()
{                   //   mark-space multivib
  unsigned long currentMillis = millis () ;
  if  (currentMillis - previousMillis >  timA)
  {
    previousMillis = currentMillis ;
    if  (ledState == LOW )
    {  ledState = HIGH ;
    }  
    digitalWrite  (ledPin, ledState) ;
  }
  if  ((ledState == HIGH)  && (currentMillis - previousMillis > timB ))
  digitalWrite  (ledPin, LOW) ;
 

valX = digitalRead (ledPin) ;
valY = digitalRead (RCLCK) ;

if (valX == HIGH)
  digitalWrite (CLCK, HIGH) ; 
  else
  digitalWrite (CLCK, LOW) ;



  measurement = analogRead (A7);
  difference = abs (setPoint - measurement);
  stepSize = difference  ;
  
  if (measurement < setPoint)
  {
    pulseWidth += stepSize / 2;
    if (pulseWidth > 255) pulseWidth = 255;
  }
  
  if (measurement > setPoint)
  {
    pulseWidth -= stepSize  ;
    if (pulseWidth < 0) pulseWidth = 0;
  }
  analogWrite (10, pulseWidth);
  delay (10);
  
                    // take a number of analog samples and total
    while (sample_count < SAMPLES) {
                     // sample each channel A0 ... A3
        for (l_cnt = 0; l_cnt < 4; l_cnt++) {
            sum   [l_cnt] += analogRead  (A0 + l_cnt);
        }
        sample_count++;
        delay(2);
    }
                  // calculate voltage for each channel
    for (l_cnt = 0; l_cnt < 4; l_cnt++) {
        voltage[l_cnt] = ((float)sum[l_cnt] / (float) SAMPLES * V_REF) / 1024.0;
    }

    lcd.setCursor(0, 0);
    lcd.print("+ ");
    lcd.print(voltage[0] * 2.000, 2);
    lcd.print ("A");
    
    lcd.setCursor(0, 1);
    lcd.print("- ");
    lcd.print(voltage[1] * 2.000, 2);
    lcd.print ("A");
    // voltge 3 - C (pin A2)
    lcd.setCursor(8, 0);
    lcd.print("  ");
    lcd.print(voltage[2] * 5.830, 2);
    lcd.print("v");
    // voltage 4 - D (pin A3)
    lcd.setCursor(8, 1);
    lcd.print("  ");
    lcd.print(voltage[3] * 4.295, 2);
    lcd.print("v");
    
    // reset count and sums
    sample_count = 0;
    for (l_cnt = 0; l_cnt < 4; l_cnt++) {
        sum[l_cnt] = 0;
    }
    
}
Testing to find/solve problem.
Looking at line 69 : if ( valX == HIGH)...
I can get output (pin 12 for testing) as expected to be copy of ledPin = 13.
But then I select valY which is the output to RCLCK (pin 6) in order to gate it with software, I get a continuous HIGH output (pin 12), and no data from Arduino to the '595 while I KNOW that the data is there and correct, i.e. the data is coming out of pin 6 because I can control it with hardware.

What am I doing wrong?
 
Last edited by a moderator:

I have tried another solution which reduces the display to about twice per second.
Looking at 74x595 specsheet (Table 1. Function Table) ......
Testing to find/solve problem.
Looking at line 69 : if ( valX == HIGH)...
I can get output (pin 12 for testing) as expected to be copy of ledPin = 13.
But then I select valY which is the output to RCLCK (pin 6) in order to gate it with software, I get a continuous HIGH output (pin 12), and no data from Arduino to the '595 while I KNOW that the data is there and correct, i.e. the data is coming out of pin 6 because I can control it with hardware.

What am I doing wrong?

No questions or suggestions for 2 weeks!
Or are we stumped again?
I am looking for suggestions to solve a problem.
Thank you.
 

No questions or suggestions for 2 weeks!
Or are we stumped again?
I am looking for suggestions to solve a problem.
Thank you.

Sorry man, I read the whole thread twice and couldn't understand the problem. At the beginning the problem is the quick refresh rate. So far so good. Then you somehow managed to solve it with diodes and resistors (!), but a schematic is not provided. And you need to implement this hardware solution (whatever that is) to the software. You provide a long code, waiting for other people to understand the problem in line 69, but still there is no line counting in your code! And what is that valX =HIGH, am I suppose to understand? Or should I guess what pin12 does?

I KNOW that the data is there and correct, i.e. the data is coming out of pin 6 because I can control it with hardware.
Really now?

Honestly I am not trying to insult you, just to help you restate the problem in a more appropriate and smart way. Solutions have been given, Kalman's filter, simple averaging. And since you look confident with the 595, it seems you have everything you need.

Regards.

- - - Updated - - -

Easyrider83 said:
I'm using Kalman's filter. I gave the code on this forum. Try to search yourself.
Hi easyrider. I found the code. I have never used this filter, but I know that it is proven in many aspects of automation. However it uses float numbers which means code size and execution time penalty. Have you ever used a simple averaging method with latest values stored in a table? If so, then what is the advantage of using this technique, instead of simple averaging?

Thanks.
 

Obviously the problem described in the original problem can be solved with pure software means, adjusting the display update frequency to a reasonable rate of 3 to 4 per second, and filtering of measurement values as far as needed.

I don't think that adjusting the update rate has anything to do with "gating" the hardware outputs, as already mentioned in post #2. Instead you would simply reduce the rate of calling LCD data output routines. The PWM control loop should probably run at a higher rate. You can e.g. perform the output every Nth PWM control cycle.

Why no one did answer to post #6? Because Adri67 simply doesn't hear?

what is the advantage of using this technique, instead of simple averaging?
A Kalman filter has advantages in filtering varying measurement data, often multi-dimensional, e.g. GPS readings of an object in movement. I don't see it's meaningful for battery charger voltage and currents.

If the input data sequence contains deterministic disturbances, no only pure random noise, a low-pass filter could be advantageous compared to a simple average with rectangular window.
 
  • Like
Reactions: alexxx

    alexxx

    Points: 2
    Helpful Answer Positive Rating
Hi,

As with all analog to digital systems: expect a jump of at least one LSB.

Filters may reduce the peak-to-peak noise, but the jump of at least 1 LSB still remains.
Independent of update rate, independent of resolution...

The only way I see to solve this is to add some hysteresis.
But this doesn't improve accuracy, nor it does improve any other measurement quality.
It's just an visual improvement.

Klaus
 

It's just an visual improvement.
Really. A hysteresis that freezes the display makes me wonder if the measurement is still live.
From a signal theory viewpoint, adding hysteresis is the road to ruin.
 

Hi,

I totally agree.

***
I´ve a high quality brand digital true RMS multimeter.
It has 0.1mV resolution, but for all input from 0.0mV ... 1.9mV it just shows "0.0 mV",
then it immediately starts with "2.0mV"

I really don´t like this "feature".
It maybe makes the reading more "nice", but at the same time more "wrong".

Klaus
 

Hi easyrider. I found the code. I have never used this filter, but I know that it is proven in many aspects of automation. However it uses float numbers which means code size and execution time penalty. Have you ever used a simple averaging method with latest values stored in a table? If so, then what is the advantage of using this technique, instead of simple averaging?
Yes, there are few simple alghorithms that can be tried also. You collecting some data to array, calculating average, then excluding all elements (just replacing by average) that is far from average more than some value, than calculating average again. This will reduce some noise spikes.
 

I have tried another solution which reduces the display to about twice per second.
Looking at 74x595 specsheet (Table 1. Function Table) when RCLCK goes high (and SER, SRCLCK, SRCLR and OE are all X [don't care] ), the function is quoted as "Shift register data is stored in the storage register". I then created an oscillator with adjustable mark-space to "gate" the RCLCK feeding the '595.
Now using diodes and resistors I got this working perfectly with display changing about twice per second.
The problem now is to replace the gate hardware with software.


Pin 13 output is a sq.wave (400mS HIGH /100mS LOW). The data from Arduino (pin 6) is sent to the '595 normally while pin 13 is LOW but when pin 6 is HIGH data is blocked and input of the '595 (pin 12) remains HIGH so the display freezes.
This seems to work okay but I can't do this with software, i.e. without the resistor and diode.
And then : is there a better alternative to (a) freezing the display, or (b) smoothing input?


I have tried several options with hardware using R-C filtering and software (average, smoothing, etc.) without success.
Perhaps I am doing either/both incorrectly and that's why I am looking for help to find a suitable alternative..
The main thing to bear in mind is that the input varies considerably due to PWM.
I cannot smoothe the input sufficiently to give a "moderately smooth" ouput.
 

This seems to work okay but I can't do this with software, i.e. without the resistor and diode.

Is it another issue, or are you assuming that it is related to the original question ?

I have tried several options with hardware using R-C filtering and software (average, smoothing, etc.) without success.

Why dont't you mention how much is this value jittering.
As far as I can see, all thinkable options have already been raised in this discussion
 

Hi,
I´ve a high quality brand digital true RMS multimeter.
It has 0.1mV resolution, but for all input from 0.0mV ... 1.9mV it just shows "0.0 mV",
then it immediately starts with "2.0mV"

I really don´t like this "feature".
It maybe makes the reading more "nice", but at the same time more "wrong".

Cannot disagree.
My FLUKE 17B seems to be okay with low DC voltages.
It seems that the conversion AC - DC on some of these ("cheap") DMMs is a problem.
But then PWM becomes part DC - part AC so we sit with the same problem. Even at voltages not close to zero.
 

Hi,

Sorry for the rest of the text: A lot of criticism. Don´t get angry about my words. I want the best for you and your application.

********

You don´t analyze and cure the root problem.
Instead of drawing a timing diagram of your signal flow you do some random try and error.
Now you try with brute force to kill some data flow to the display.
You kill with hardware the datastream that you build by yourself with software.
It´s like you have your kitchen oven allways full ON, and in case you don´t need the heat you pour a lot of water on it to cool it down.

This is not a "quick and dirty" solution, maybe it´s only "dirty", but I assume it again is no solution at all.

******
I don´t know how you generate the signal on pin13. But why the nasty diode solution? Why not read the state of the pin in software and then decide in software whether to update the display or not.

******
But the main problem is the analog signal.
* you didn´t give us useful information about this signal. No schematic, no description like: frequency, signal wavform, expected ripple and so on.
* don´t follow my recommendation of post#5 for a fixed and known sample rate, but complain that your solution does not work. (I say: no wonder!)

******
Please start to encircle the problem. And follow the direction of the signal: Step by step. From the analog signal, analog filtering, ADC, averaging / digital filtering, to display update.

The thread is now more than two months old. If you follow our recommendations i bet you have a clean solution within two days (maybe two hours).

*****
If you want to go this way:
* post the schematic of the analog signal. From source to ADC.
* give informations like PWM frequency, voltages, currents...
* use a scope and show us the anlog signal directely at the ADC input. Time scale 10ms/div.. Vertical scale for best view.
* that´s it. Then we go the next step.

Klaus
 

Pin 13 output is a sq.wave (400mS HIGH /100mS LOW). The data from Arduino (pin 6) is sent to the '595 normally while pin 13 is LOW but when pin 6 is HIGH data is blocked and input of the '595 (pin 12) remains HIGH so the display freezes

Just a side issue, but are you aware that in Arduino pin 13 is internally shared with a resistor/led diode as default ? Regardless of having understood how the bit banging question above could be connected to the jitter effect, it would be advisable to think about using another pin of the board in order to avoid some unwanted loading effect.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top