Go Down

Topic: processing time for lcd (Read 420 times) previous topic - next topic

tiara

Hi everyone. I'v tried to running my 3 phase inverter circuit with this main_code below and it worked properly (I used Arduino UNO).
Code: [Select]

float port1 = 11;
float port2 = 10;
float port3 = 9;
int f = 50;

void setup() {
Serial.begin(9600);
pinMode(port1, OUTPUT);
pinMode(port2, OUTPUT);
pinMode(port3, OUTPUT);
}

void loop() {
  //1st session
  analogWrite(port1, 255);
  analogWrite(port2, 0);
  analogWrite(port3, 255);
  Serial.println("1 0 1");
  delay(1/(6*f));
  //2nd session
  analogWrite(port1, 255);
  analogWrite(port2, 0);
  analogWrite(port3, 0);
  Serial.println("1 0 0");
  delay(1/(6*f));
  //3rd  session
  analogWrite(port1, 255);
  analogWrite(port2, 255);
  analogWrite(port3, 0);
  Serial.println("1 1 0");
  delay(1/(6*f));
   //4th session
  analogWrite(port1, 0);
  analogWrite(port2, 255);
  analogWrite(port3, 0);
  Serial.println("0 1 0");
  delay(1/(6*f));
   //5th session
  analogWrite(port1, 0);
  analogWrite(port2, 255);
  analogWrite(port3, 255);
  Serial.println("0 1 1");
  delay(1/(6*f));
   //6th session
  analogWrite(port1, 0);
  analogWrite(port2, 0);
  analogWrite(port3, 255);
  Serial.println("0 0 1");
  delay(1/(6*f));
}

The problem came when I tried to apply it with lcd and switch buttons for more frequencies variant (30Hz, 40Hz, and 50Hz). I modified my code and it didn't work (my induction motor didn't rotate). This is my modified code :
Code: [Select]

#include <LiquidCrystal.h>
float PWM1 = 11;
float PWM2 = 10;
float PWM3 = 9;
int f = 50;
const int PIN_A0 = A0;
const int PIN_A1 = A1;
const int PIN_A2 = A2;
const int PIN_RS = 2;
const int PIN_E = 3;
const int PIN_DB4 = 4;
const int PIN_DB5 = 5;
const int PIN_DB6 = 7;
const int PIN_DB7 = 8;
LiquidCrystal lcd(2, 3, 4, 5, 7, 8);

void setup() {
  pinMode(PWM1, OUTPUT);
  pinMode(PWM2, OUTPUT);
  pinMode(PWM3, OUTPUT);
  pinMode(PIN_A0, INPUT_PULLUP);
  pinMode(PIN_A1, INPUT_PULLUP);
  pinMode(PIN_A2, INPUT_PULLUP);
  lcd.begin(16, 2);
  Serial.begin(9600);
}

void loop() {
  int TOMBOL1 = digitalRead(PIN_A0);
  int TOMBOL2 = digitalRead(PIN_A1);
  int TOMBOL3 = digitalRead(PIN_A2);
  if(TOMBOL1 == LOW && TOMBOL2 == HIGH && TOMBOL3 == HIGH){
    lcd.clear();
    lcd.print("3_PHASE INVERTER");
    lcd.setCursor(0, 1);
    lcd.print("Freq = 50Hz");
    frequency50();
  }
  else if(TOMBOL1 == HIGH && TOMBOL2 == LOW && TOMBOL3 == HIGH){
    lcd.clear();
    lcd.print("3_PHASE INVERTER");
    lcd.setCursor(0, 1);
    lcd.print("Freq = 40Hz");
    frequency40();
  }
  else if(TOMBOL1 == HIGH && TOMBOL2 == HIGH && TOMBOL3 == LOW){
    lcd.clear();
    lcd.print("3_PHASE INVERTER");
    lcd.setCursor(0, 1);
    lcd.print("Freq = 30Hz");
    frequency30();
  }
  else{
    lcd.clear();
    lcd.print("3_PHASE INVERTER");
    lcd.setCursor(0, 1);
    lcd.print("Standby Mode");
    Serial.println("Standby");
    delay(1000);
  }
}

void frequency50() {
  //1st session (101)
  analogWrite(PWM1, 255);
  analogWrite(PWM2, 0);
  analogWrite(PWM3, 255);
  delay(1/(6*f));
  //2nd session (100)
  analogWrite(PWM1, 255);
  analogWrite(PWM2, 0);
  analogWrite(PWM3, 0);
  delay(1/(6*f));
  //3rd session (110)
  analogWrite(PWM1, 255);
  analogWrite(PWM2, 255);
  analogWrite(PWM3, 0);
  delay(1/(6*f));
   //4th session (010)
  analogWrite(PWM1, 0);
  analogWrite(PWM2, 255);
  analogWrite(PWM3, 0);
  delay(1/(6*f));
   //5th session (011)
  analogWrite(PWM1, 0);
  analogWrite(PWM2, 255);
  analogWrite(PWM3, 255);
  delay(1/(6*f));
   //6th session (001)
  analogWrite(PWM1, 0);
  analogWrite(PWM2, 0);
  analogWrite(PWM3, 255);
  delay(1/(6*f));
  Serial.print("50Hz");
}

void frequency40() {
  //1st session (101)
  analogWrite(PWM1, 204);
  analogWrite(PWM2, 0);
  analogWrite(PWM3, 204);
  delay(1/(6*f));
  //2nd session (100)
  analogWrite(PWM1, 204);
  analogWrite(PWM2, 0);
  analogWrite(PWM3, 0);
  delay(1/(6*f));
  //3rd session (110)
  analogWrite(PWM1, 204);
  analogWrite(PWM2, 204);
  analogWrite(PWM3, 0);
  delay(1/(6*f));
   //4th session (010)
  analogWrite(PWM1, 0);
  analogWrite(PWM2, 204);
  analogWrite(PWM3, 0);
  delay(1/(6*f));
   //5th session (011)
  analogWrite(PWM1, 0);
  analogWrite(PWM2, 204);
  analogWrite(PWM3, 204);
  delay(1/(6*f));
   //6th session (001)
  analogWrite(PWM1, 0);
  analogWrite(PWM2, 0);
  analogWrite(PWM3, 204);
  delay(1/(6*f));
  Serial.print("40Hz");
}

void frequency30() {
  //1st session (101)
  analogWrite(PWM1, 153);
  analogWrite(PWM2, 0);
  analogWrite(PWM3, 153);
  delay(1/(6*f));
  //2nd session (100)
  analogWrite(PWM1, 153);
  analogWrite(PWM2, 0);
  analogWrite(PWM3, 0);
  delay(1/(6*f));
  //3rd session (110)
  analogWrite(PWM1, 153);
  analogWrite(PWM2, 153);
  analogWrite(PWM3, 0);
  delay(1/(6*f));
   //4th session (010)
  analogWrite(PWM1, 0);
  analogWrite(PWM2, 153);
  analogWrite(PWM3, 0);
  delay(1/(6*f));
   //5th session (011)
  analogWrite(PWM1, 0);
  analogWrite(PWM2, 153);
  analogWrite(PWM3, 153);
  delay(1/(6*f));
   //6th session (001)
  analogWrite(PWM1, 0);
  analogWrite(PWM2, 0);
  analogWrite(PWM3, 153);
  delay(1/(6*f));
  Serial.print("30Hz");
}


For more information I'v tried to running my project only with main_code + lcd and it also didn't work. Shoud I lessen 6th session pwm with processing time for lcd listing? (I used lcd QC1602A v2.0). For anyone, please help me solve this problem. Thank you. Regards, Tiara.

groundfungus

What is output on the LCD when you try the buttons?  Does the LCD show anything? 

Code: [Select]
loat port1 = 11;
float port2 = 10;
float port3 = 9;


Why are the pins assignments float data type.?

floresta

It looks like every time you go through the loop, regardless of the path, you perform these two steps:
Code: [Select]
   lcd.clear();
   lcd.print("3_PHASE INVERTER");

Since the information doesn't change it should be written to the LCD once, in setup().  Also, you don't need to clear the LCD since that is done during it's initialization.

In your loop make sure that all of the messages for the second line are the same length.  This way you don't have to clear out the old message - you just overwrite it with the new one.


Don

tiara

hi everyone, thanks for your response
@groundfungus
when I tried the buttons, lcd showed correct frequency according to the button. Everything  worked properly, except my induction motor, it didn't rotate, it just buzzing. oh I use float type just to get more accurate number, I suppose that it can be int type.
@floresta
thanks for your advice  :) . I will try it and tell you about the result. Do you know about how much time is needed by arduino to process lcd listing? I suppose that problem came because arduino need more time to execute the lcd listing, so the pwm delay (each session) become unbalance anymore, and maybe thats why my induction motor didn't rotate. I'v tried lessen 6th session delay with 60ns (according to "read data output delay" parameter from QC1602A v2.0 datasheet) and it made my induction motor rotated but very slow and still buzzed.

floresta

Quote
Do you know about how much time is needed by arduino to process lcd listing?


It's not the Arduino that needs time 'to process lcd listing', it's the LCD controller that needs the time.  The Arduino provides this needed time in the form of a 'delay' and in the case of the LiquidCrystal library this delay is 'blocking' which means that nothing else is done by the Arduino during that time.  The net result is the same and your analysis of the problem may very well be correct.

To answer your question - once the Arduino has sent information to the LCD module it's controller requires approximately 40 uSec to process the information in most cases.  This would be 40 uS for each character.  The Clear display command and the Return home command each require considerably longer, about 1.5 mSec which is one reason to try and avoid using Clear in a fast loop.

To give you some perspective the Arduino typically requires 62.5 nSec to execute a command.  This means that the Arduino could have executed 640 commands while it was waiting for each character in a message and it could have executed 24000 commands while waiting for the display to clear.

I hope I got all my numbers correct.  In any case the basic idea is that the Arduino is very much faster than the LCD.  This is a situation where interrupts might be useful. 


Don

tiara

hi floresta
Your answer is really awesome. I still trying to modify my listing and I will try it in my inverter circuit as soon as I can. I will inform you the result. Thanks a lot  :)

MidiMan

Hi floresta,

also to me your answer is really useful. I have a project with a midi controller that has to send midi commands in real time (midi clock) but in the same an lcd display has to be updated when AD inputs (from foot pedals) change their value. I found out that my Arduino Mega does the job very well but any update of the display (a 20x2 LCD) takes time that delays the clock output.

Question: How would you suggest to accomplish this with interrupts? Is it about rewriting the LCD library?

H.

floresta

Quote
... Is it about rewriting the LCD library?


No.  The LCD is the low priority device in the system so this is what would be interrupted when something more important had to be done.  The library should not have to be changed.

Quote
I have a project with a midi controller that has to send midi commands in real time . . .


It looks like this is the high priority part of the system.  You would write your program to generate an interrupt when it was time to send a midi command.  The interrupt service routine would either send the midi command (if this could be accomplished quickly) or set a flag so that the main program would know it had to send the command.

Don

MidiMan

Don,

many thanks for your reply and the useful hints. My selfeducation on Arduino hasn't come as far as interrupts yet so I'll  better dive into that topic. It sounds like it could solve quite some issues I have with making my code more efficient.  8)

Henning

bperrybap


The Clear display command and the Return home command each require considerably longer, about 1.5 mSec which is one reason to try and avoid using Clear in a fast loop.

With the stock LiquidCrystal library the total overhead will be closer to 3ms.
There is a 2ms blind delay after the CLEAR and HOME commands are sent to the display.
Then there is all the unneeded pinMode() calls to set up the 4 data pins every single time
for each nibble sent. (not just before sending each byte but for each nibble!)
Along with a few other non optimal things and it ends up pushing closer to between 2.5 and 3ms.

There are other libraries like fm's that are considerably faster than the stock LiquidCrystal library.

In terms of avoiding clear() and home(),
it is usually faster to overwrite the entire LCD with spaces than to call clear()
because character updates and cursor positioning are so much faster than the CLEAR command.


--- bill

MidiMan

@ floresta:

Looking at the structure and options for interupts I am not sure if I could accomplish what I need by using interrupts. While a quite complex loop is running my code shall constantly do something like this:

if (micros() > (n + lastmicros)){
    send a serial command
    lastmicros = micros();
}

n is a variable that is set by the main program in order to define the interval time.
Currently I have inserted these lines of code many (many!) times in my main code in order to achieve the required precision. However, sometimes the LCD must be updated while the real time requirement is given. An interrupt would probably save a lot of code lines (and precious RAM!) while even gaining more precision.

So my question is like this:

Can I set up a timer interrupt in my setup section that is 'configurable' by a variable which is set by my main program loop? (n in the above example)

Hope my question is clear, please forgive me my code writing unprofessionalism, I am a only a user (musician) who needs the function.  :smiley-eek-blue:

Henning





MidiMan

Just something to add that I forgot:

The precision to achieve is like this:

The board shall send Midi Clock signals through a serial port (which btw works fine in principle). Midi clock frequqncy is controllable through a variable in the range of 40-300 BPM. (Beats per Minute)
A Midi Clock frequency is defined as 24 x BPM . Thus for a  max. BPM of 300 the calculation is like this:

300 BPM = 300/60 = 5Hz
5 Hz * 24 = 120 Hz = one serial output every 8.33 ms
The max. tolerated deviation is approx 1% which would be roughly 83us.

This makes clear why the updating of an LCD with delays in the range of some ms doesn't really work. The timer needs to have strict priority but must be configurable with regard to its intervall. Is that somehow doable with interrupts?

Thanks,
Henning

Go Up