[ARM] Problem with RPM showing on TFT

Status
Not open for further replies.

betuse

Junior Member level 3
Joined
Oct 17, 2013
Messages
26
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Visit site
Activity points
173
Hi collegues,
I use EasyMx for Stellaris with ARM C4 mcu, mikroc pro for arm,
I measure RPM on DC motor with encoder, and show on TFT every 1 sec,
everithing is Ok, but I can not show clear RPM number on TFT because new numbers shows over previous numbers...
after a short time I see only some smeared color...
I think I am clear with explanation,
can somebody advice how to "refresh" new number of RPM with clear previous number?
the code is

Code:
#include "Resources.h"
sbit ENCODER at GPIO_PORTG_DATA.B4;
sbit ENCODER_Direction at GPIO_PORTG_DIR4_bit;

unsigned int RPM, Cnt = 0;
unsigned char Txt[4];
unsigned char DsplyCnt = 0;

// TFT module connections
char TFT_DataPort at GPIO_PORTJ_DATA;
sbit TFT_RST at GPIO_PORTH_DATA5_bit;
sbit TFT_RS at GPIO_PORTG_DATA7_bit;
sbit TFT_CS at GPIO_PORTH_DATA6_bit;
sbit TFT_RD at GPIO_PORTC_DATA5_bit;
sbit TFT_WR at GPIO_PORTH_DATA4_bit;
sbit TFT_BLED at GPIO_PORTA_DATA3_bit;
char TFT_DataPort_Direction at GPIO_PORTJ_DIR;
sbit TFT_RST_Direction at GPIO_PORTH_DIR5_bit;
sbit TFT_RS_Direction at GPIO_PORTG_DIR7_bit;
sbit TFT_CS_Direction at GPIO_PORTH_DIR6_bit;
sbit TFT_RD_Direction at GPIO_PORTC_DIR5_bit;
sbit TFT_WR_Direction at GPIO_PORTH_DIR4_bit;
sbit TFT_BLED_Direction at GPIO_PORTA_DIR3_bit;
// End TFT module connections

void DrawScr() {
  TFT_Init_ILI9341_8bit(320, 240);
  TFT_Fill_Screen(CL_WHITE);
  TFT_Set_Pen(CL_Black, 2);
  TFT_Line(20, 205, 300, 205);
  TFT_Line(20,  40, 300,  40);
  TFT_Set_Font(&HandelGothic_BT21x22_Regular, CL_RED, FO_HORIZONTAL);
  TFT_Write_Text("DC   Motor   with   LMD18200", 40, 14);
  TFT_Set_Font(&HandelGothic_BT21x22_Regular, CL_RED, FO_HORIZONTAL);
  TFT_Write_Text("Tiva C", 19, 210);
  TFT_Set_Font(&HandelGothic_BT21x22_Regular, CL_RED, FO_HORIZONTAL);
  TFT_Write_Text("TI", 220, 210);
  TFT_Set_Font(&HandelGothic_BT21x22_Regular, CL_Black, FO_HORIZONTAL);
  TFT_Write_Text("Speed  (RPM):  ", 90, 50);
  TFT_Set_Font(&HandelGothic_BT21x22_Regular, CL_Black, FO_HORIZONTAL);
  TFT_Write_Text("Direction   (CW / CCW):  ", 60, 120);
}

void Timer0A_interrupt() iv IVT_INT_TIMER0A_16_32_bit {
   TIMER_ICR_TATOCINT_bit = 1;
   RPM = 6*Cnt;                                          // Speed in RPM
   IntToStr(RPM, Txt);                                   // Convert to string
   Cnt = 0;
   DsplyCnt++;
      if(DsplyCnt == 10) {                               // 1 s ?
         DsplyCnt = 0;
         TFT_Set_Font(&HandelGothic_BT21x22_Regular, CL_Red, FO_HORIZONTAL);
         TFT_Write_Text(Txt, 125, 80);
      }
}

void main(){
   GPIO_Digital_Input(&GPIO_PORTG, _GPIO_PINMASK_4);
   GPIO_Digital_Output(&GPIO_PORTF, _GPIO_PINMASK_4);    // Enable digital output on PORTF, bit4 za PWM
   GPIO_PORTF_DATA.B4 = 1;                               //PWM pinot od LMD, vrti
   
   TFT_Set_Default_Mode();
   DrawScr();

   SYSCTL_RCGC1_TIMER0_bit = 1;                          // Enable clock gating for timer module 0
   EnableInterrupts();                                   // Enables the processor interrupt.

   TIMER_CTL_TAEN_bit = 0;                               // Disable timer
   TIMER0_CFG = 0;                                       // Set 32-bit timer configuration
   TIMER0_TAMR |= 2;                                     // Set periodic mode
   TIMER0_TAILR = Get_Fosc_kHz()*100;                    // Set interval load
   NVIC_IntEnable(IVT_INT_TIMER0A_16_32_bit);            // Enable timer interrupt
   TIMER_IMR_TATOIM_bit = 1;                             // Enable time-out timer A interrupt
   TIMER_CTL_TAEN_bit = 1;                               // Enable timer A
   
      while(1){
         while(ENCODER == 0); // Wait if 0
         Cnt++; // Increment encoder count
         while(ENCODER == 1); // Wait if 1
      }
}

I use interrupt for 100ms, and count encoder pin,
and calculate RPM with encoder holes number....

if somebody have solution please share with me,
best regards
 

one technique I have used in the past is
1. assume background is white and text is displayed in black
2. when new text is to be displayed rewrite the orignal text in white (to erase it) then the new text in black

this requires maintaining a record of the text writen where it is etc so it can be erased and replaced with new text
 
Reactions: betuse

    betuse

    Points: 2
    Helpful Answer Positive Rating
Yes Horace1, background color is white and text is black,
if I understand you well I will try,
best regards

- - - Updated - - -

Me again,
to complicated for me right now,
 

I was thinking of soemthing along the lines of
Code:
void Timer0A_interrupt() iv IVT_INT_TIMER0A_16_32_bit {
   static unsigned char OldTxt[4]={' '};
   TIMER_ICR_TATOCINT_bit = 1;
   RPM = 6*Cnt;                                          // Speed in RPM
   IntToStr(RPM, Txt);                                   // Convert to string
   Cnt = 0;
   DsplyCnt++;
      if(DsplyCnt == 10) {                               // 1 s ?
         DsplyCnt = 0;
         // erase old text
         TFT_Set_Font(&HandelGothic_BT21x22_Regular, CL_WHITE, FO_HORIZONTAL);
         TFT_Write_Text(OldTxt, 125, 80);
         // write new text
        TFT_Set_Font(&HandelGothic_BT21x22_Regular, CL_Red, FO_HORIZONTAL);
         TFT_Write_Text(Txt, 125, 80);
         // save currect text for erase
         memcpy(OldTxt, Txt, 4);
      }
}
you save the text just written into static variable OldTxt which on the next output of data you write in white to erase the old text before writing the new text
 
Reactions: betuse

    betuse

    Points: 2
    Helpful Answer Positive Rating
Horace1,
RPM in my case is app 870,
your advice working but only for number of hundred's (8), overwriting is still on number of ten's and one's...
 

you need to make sure that the text takes up the same space no matter what the values, e.g. by using a fixed field width

rather than using
Code:
IntToStr(RPM, Txt);
use
Code:
sprintf(Txt,"%3d", RPM);
to write in a field of three characters wide
you also need to make sure that the font you use is fixed width, e.g. courier, otherwise spaces take less space than numbers
 
Reactions: betuse

    betuse

    Points: 2
    Helpful Answer Positive Rating
Great, it is work,
thanks horace1,
best regards
 

Horace1, one more question for you, according previous project you help me,
now I need to save in array, every 1ms, RPM from motor, and send to PC via UART,
exactly,
every 1ms, I read RPM value, and send to PC via UART i array...

can you advice how to send via UART RPM value?
RPM is integer, so I need to split on two digit, right?
can you advice please?

best regards
 

say RPM is a 16 bit integer and UARTPutChar() sends a byte
Code:
UART2PutChar(RPM >> 8);    // send most significant byte
UART2PutChar(RPM);    // send least significant byte
 
Reactions: betuse

    betuse

    Points: 2
    Helpful Answer Positive Rating
Horace1,
at the start sorry because I wrote directly to you, but because you help me with concrete solution, I think is not a problem,
I have several conclusion:
I read RPM app 890 on TFT, but expected value need to be app 2000 RPM,
I check my calculations and I think I have a problem with slow procedure for TFT writing and I lost some values from RPM?
is it possible?
About solution how to save measured RPM values with some faster procedure, I think is better to create array, with RPM values, for example read every 10ms, write to array, and after some time for example 3 or 5 sec save that array in RAM or FLASH of MCU?
please share with me your opinion?
best regards
 

just thinking about the RPM for now
looking at your code you may have a number of problems
1. you are outputing to the TFT in the timer interrupt service routine - one should keep interrupt servive routines as short as possible or you could miss intterupts and delay code execution elsewhere - move this code into main()
2. you are incrementing your RPM count in main() - your long timer interrupts could well cause you to miss counts - can you use interrupts to count the RPM? on a PIC I would enable 'interrupt on change' so that changes on the pin cause an interrupt and increment the count

note that if you expect your RPM values to be 2000 (four character long) make your Txt array larger to allow for the terminating 0, e.g.
Code:
unsigned char Txt[6];
 
Last edited:
Reactions: betuse

    betuse

    Points: 2
    Helpful Answer Positive Rating
I think better way will be to store Cnt on array, without TFT write procedure...
for example store Cnt on vector every 10ms,
do this for example 10 sec,
after 10 sec, send the vector to PC via UART,
Horace1, can you help with concrete advice how to create vector (probably for example
int Cnt_vector[1000]
and save Cnt on that vector...
after send vector to PC...
thanks again and
best regards
 

I assume you would double buffer so you don't loose data while transmitting the block evry 10 seconds
However, if you are transmitting the data using a UART cannot see any great advantage in saving the data to an array and sending a block every 10 seconds - why not send a sample as soon as you have sampled it every 100mSec?
what baud rate are you planning to use?
the PC can receive the data and plot it or save it to a file or what every you wish to do with it
have you considered using USB to transmit your data to a PC?
 
Last edited:
Reactions: betuse

    betuse

    Points: 2
    Helpful Answer Positive Rating
Horace1,
my intention is to create only one block of Cnt for 10 sec, and send to PC,
not several blocks every 10 sec,
baud rate 57600,
you ask : why not send a sample as soon as you have sampled it every 100mSec?
I think because UART need some time for finish the transfer, to create array and after send to PC,
USB? I dont have any experiences with USB...
 

I was thinking of a double buffer, after 10 seconds you transmit a block and start filling another so you don't loose any data
at 57600baud it will take you approx third of a second to transmit 2000 characters - what happens to your TFT display of results in this time?
if you just transmit a two byte integer as soon as you sample it there should be practically no delay - I would assume the microcontroller UART has a number of FIFO transmit buffers

- - - Updated - - -

if your baud rate is 57600baud (approx 500 character/sec maximum) you probably don't need to transmit your data in binary
e.g. taking 100 samples/second transmitted as 5 characters (2000 plus \n)

this has the advantage that you can look at the incomming data on a PC using a terminal emulator (such as hyperterm or teraterm) and see if it is making sense - no need to convert from binary to a human readable form
 
Reactions: betuse

    betuse

    Points: 2
    Helpful Answer Positive Rating
TFT display? I will not use it,
only measure Cnt from encoder (not convert to RPM), save in array, after 10 sec, send array to PC...
how can I create array with 1000 members, each with max 4 digit dec number?
also how to send that array via UART?
 

TFT display? I will not use it,
only measure Cnt from encoder (not convert to RPM), save in array, after 10 sec, send array to PC...
how can I create array with 1000 members, each with max 4 digit dec number?
also how to send that array via UART?
store the data as integer convert to characters just before transmission, e.g. code something along the lines of
Code:
int RPM[1000];
int RPMindex=0;

void Timer0A_interrupt() iv IVT_INT_TIMER0A_16_32_bit {
   TIMER_ICR_TATOCINT_bit = 1;
   // store data in array until  it is full
   if(RMPindex<1000) RPM[RPMindex++] = 6*Cnt;    // Speed in RPM
   Cnt = 0;
   DsplyCnt++;
 }


int mian(void)
{

...


while(1)
    {
     // if array is full transmit data
    if(RPMindex == 1000)
    {
      for(i=0;i < 1000; i++) 
       {
          IntToStr(RPM[i], Txt);   // Convert to string
          UARTprintString(Txt); // transmit the string
          }
          RPMindex=0;       // reset array index
      }    
}

}
 
Reactions: betuse

    betuse

    Points: 2
    Helpful Answer Positive Rating
Horace, in while (1) I have Cnt procedure
Code:
while(1){
         while(ENCODER == 0);                            // wait if 0
         Cnt++;                                          // Inc ENCODER
         while(ENCODER == 1);                            // wait if 1
}

Your advice for "if array is full" is also in while(1), I will have a problem if I put together?
 
Last edited:

try putting them together

while you are transmitting the data no more data will be collected unless you go to a double buffer then you will have to rethink the loop
 
Reactions: betuse

    betuse

    Points: 2
    Helpful Answer Positive Rating
MikroC for ARM dont support UARTprintString(Txt);
only
UART_Write(Txt); and
UART_Write_Text(Txt);
what is better solution to print that string? UART_Write_Text(Txt);?

- - - Updated - - -

I receive on UART terminal something like this
098 136 099 200 098 128 070 000 116 035 244 017
how can I "read" this number like RPM?

here is the code:

Code:
sbit ENKODER at GPIO_PORTH_DATA.B0;     //encoder PH0

unsigned int Cnt = 0;
unsigned char Txt[4];
int RPM[1000];
int RPMindex = 0;
int i = 0;

void Timer0A_interrupt() iv IVT_INT_TIMER0A_16_32_bit {  //interapt
   TIMER_ICR_TATOCINT_bit = 1;
   if(RPMindex < 1000) RPM[RPMindex++] = 6*Cnt;    // Speed in RPM
   Cnt = 0;
}

void main(){
   UART0_Init(57600);
   GPIO_Digital_Input(&GPIO_PORTH, _GPIO_PINMASK_0);     //PH0 digital inpui
   GPIO_Digital_Output(&GPIO_PORTG, _GPIO_PINMASK_4);    //PG4 digital output
   GPIO_PORTG_DATA.B4 = 1;                               //motor drive

   SYSCTL_RCGC1_TIMER0_bit = 1;                          // 
   EnableInterrupts();                                   // 

   TIMER_CTL_TAEN_bit = 0;                               // 
   TIMER0_CFG = 0;                                       // 
   TIMER0_TAMR |= 2;                                     // 
   TIMER0_TAILR = Get_Fosc_kHz()*100;                    // interval 100ms
   NVIC_IntEnable(IVT_INT_TIMER0A_16_32_bit);            // Enable tajmer interapt
   TIMER_IMR_TATOIM_bit = 1;                             // Enable time-out timer A interrupt
   TIMER_CTL_TAEN_bit = 1;                               // Enable timer A

      while(1){
         // if array is full transmit data
         if(RPMindex == 1000){
            for(i = 0; i < 1000; i++){
               IntToStr(RPM[i], Txt);   // Convert to string
               UART_Write_Text(Txt); // transmit the string
            }
            RPMindex = 0;       // reset array index
         }
         while(ENKODER == 0);                            // wait if 0
         Cnt++;                                          // Inc ENCODER
         while(ENKODER == 1);                            // wait if 1
      }
}
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…