print speed with ST7565

Hi all, i'm building a instrument panel for my car, working on a tach and speedometer. I'm using a teensy with FreqMeasure libraries to read the frequency from the car sensors. Then using the u8glib and a ST7565 from adafruit for display.

In my code, without the picture loop present, the serial monitor updates rapidly with the frequency measurement. When I put the picture loop code back in, both the serial monitor and LCD only update frequency about once per sec. I don't know enough to know how to optimize this situation. Any ideas? Any obvious mistakes I'm making or slow approaches?

THanks,

#include <FreqMeasure2.h>
#include "U8glib.h"
#include <FreqMeasure.h>

float frequency;
float frequency2;
double sum=0;
int count=0;
double sum2=0;
int count2=0;

float rpm;
float mph;

U8GLIB_LM6059 u8g(15, 16, 17, 18, 19);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9

void draw(void) {
    u8g.setFont(u8g_font_unifont);
    u8g.drawStr( 75, 60, "MPH");
    u8g.drawStr( 90, 31, "RPM");
}
void setup(void) {

  Serial.begin(57600);
  FreqMeasure.begin();
  FreqMeasure2.begin();

u8g.setContrast(150);
 
}

void loop(void) {
    if (FreqMeasure2.available()) {
    // average several reading together
    sum2 = sum2 + FreqMeasure2.read();
    count2 = count2 + 1;
    if (count2 > 30) {
      frequency2 = FreqMeasure2.countToFrequency(sum2 / count2);
      mph = frequency2*0.45; //(freq* 3600s/hr *mile/8000 clicks) 
      Serial.println(mph);
      sum2 = 0;
      count2 = 0;
    }
    }
  if (FreqMeasure.available()) {
    // average several reading together
    sum = sum + FreqMeasure.read();
    count = count + 1;
    if (count > 30) {
      frequency = FreqMeasure.countToFrequency(sum / count);
      rpm = frequency/58; //(58 teeth per flywheel revolution) 
      Serial.println(rpm);
      sum = 0;
      count = 0;
    }
  }  
 
 // picture loop
  u8g.firstPage();

  do {
    draw();
      u8g.setPrintPos(0, 60);
      u8g.setFont(u8g_font_fur49n);
      u8g.print(mph); 
      u8g.setPrintPos(80, 20);
      u8g.setFont(u8g_font_fur14);
      u8g.print(rpm); 
  } 
  while( u8g.nextPage() ); 
}

You could use the double speed constructor.

U8GLIB_LM6059_2X u8g(15, 16, 17, 18, 19);

Also HW SPI could be an option, if you change the pins.

I also suggest to reduce/avoid the number of float variables.
Perhaps sum and sum2 could be replaced by integer variables.

Oliver

I changed the pins to the hardware SPI and used 2x constructor, and it didn't make any difference. Nor changing floats to int. I changed the u8glib to this one: Teensy 3.0 and u8glib | Page 3 | Teensy Forum

Do I need to do anything special to make it use HW SPI? From a different library optimized for Teensy 3.1 with a different controller: GitHub - PaulStoffregen/Adafruit_ST7735: This is a library for the Adafruit 1.8" SPI display http://www.adafruit.com/products/358 and http://www.adafruit.com/products/618

// This Teensy3 native optimized version requires specific pins
//
#define sclk 13 // SCLK can also use pin 14
#define mosi 11 // MOSI can also use pin 7
#define cs 10 // CS & DC can use pins 2, 6, 9, 10, 15, 20, 21, 22, 23
#define dc 9 // but certain pairs must NOT be used: 2+10, 6+9, 20+23, 21+22
#define rst 8 // RST can use any pin

Right now I am wired up with
SID - 11
CS - 10
A0 - 9
RST - 8
SCLK - 13

#include <SPI.h>

#include <FreqMeasure2.h>
#include "U8glib.h"
#include <FreqMeasure.h>

int frequency;
int frequency2;
int sum=0;
int count=0;
int sum2=0;
int count2=0;

int rpm;
int mph;

U8GLIB_LM6059_2X u8g(13, 11, 10, 9, 8);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9

void draw(void) {
    u8g.setFont(u8g_font_unifont);
    u8g.drawStr( 75, 60, "MPH");
    u8g.drawStr( 90, 31, "RPM");
}
void setup(void) {

  Serial.begin(57600);
  FreqMeasure.begin();
  FreqMeasure2.begin();

u8g.setContrast(130);
 
}

void loop(void) {
    if (FreqMeasure2.available()) {
    // average several reading together
    sum2 = sum2 + FreqMeasure2.read();
    count2 = count2 + 1;
    if (count2 > 30) {
      frequency2 = FreqMeasure2.countToFrequency(sum2 / count2);
      mph = frequency2*0.58; //(freq* 3600s/hr *mile/8000 clicks) 
      Serial.println(mph);
      sum2 = 0;
      count2 = 0;
    }
    }
  if (FreqMeasure.available()) {
    // average several reading together
    sum = sum + FreqMeasure.read();
    count = count + 1;
    if (count > 30) {
      frequency = FreqMeasure.countToFrequency(sum / count);
      rpm = frequency/58; //(58 teeth per flywheel revolution) 
      Serial.println(rpm);
      sum = 0;
      count = 0;
    }
  }  
 
 // picture loop
  u8g.firstPage();

  do {
    draw();
      u8g.setPrintPos(0, 60);
      u8g.setFont(u8g_font_fur49n);
      u8g.print(mph); 
      u8g.setPrintPos(80, 20);
      u8g.setFont(u8g_font_fur14);
      u8g.print(rpm); 
  } 
  while( u8g.nextPage() ); 
}

If I change the constructor to only using U8GLIB_LM6059(cs, a0 [, reset]) which is U8GLIB_LM6059(10, 9, 8) or U8GLIB_LM6059(10, 9) with reset connected to 3.3v, I don't get anything on screen. However my serial monitor shows the frequency measurement printing at 4 or 5 times/sec. With the full constructor U8GLIB_LM6059(13, 11, 10, 9) I don't need to specify reset for it to work as long as reset is connected to 3.3v

Now, If i load a sketch using the full constructor U8GLIB_DOGM128(13, 11, 10, 9) and get it running at 1 fps, and then change to U8GLIB_DOGM128(10, 9) and reload an interesting thing happens. Firstly, the DOGM128 constructor loads weird, and the screen is basically upsidedown and the top half and bottom half are switched. No surprise, since it's not a DOGM128 display. But when I reload the shortened constructor a page somewhere on screen clears and i can faintly (FAINTLY) see my frequency numbers flashing fast! I increased the contrast, and the printed number is changing so fast that its ghosting and faint to read.

So this weird glitch shows that something is able to print to the screen at a rapid frame rate, and using a hardware SPI constructor allows my serial monitor to update more quickly. I think the library just isn't allowing my teensy to use hardware spi. but the pins are set right so I don't know how to proceed. any ideas?

If I remember correctly, i did not add HW SPI support for the teensy.
In fact i was not able not spent much time to optimize U8glib for the teensy.
Basically U8glib will use the procedures in u8g_arduino_std_sw_spi.c to output the data.
You will find the following procedure:

void u8g_arduino_sw_spi_shift_out(uint8_t dataPin, uint8_t clockPin, uint8_t val)
{
  uint8_t i = 8;
  do
  {
    if ( val & 128 )
      digitalWrite(dataPin, HIGH);
    else
      digitalWrite(dataPin, LOW);
    val <<= 1;
    u8g_MicroDelay();		/* 23 Sep 2012 */
    //delay(1);
    digitalWrite(clockPin, HIGH);
    u8g_MicroDelay();		/* 23 Sep 2012 */
    //delay(1);
    digitalWrite(clockPin, LOW);		
    u8g_MicroDelay();		/* 23 Sep 2012 */
    //delay(1);
    i--;
  } while( i != 0 );
}

Optimizing this procedure will probably highly increase speed. You could start to remove the u8g_MicroDelay() procedure one by one. Also replacing digitalWrite() with something else, could speed up the code a lot.

Oliver

thanks I'll look into that!

Okay, I removed the microdelay lines, and replaced digitalWrite with digitalWriteFast, and now it's at just over 2fps. This is nice, it's twice as fast as before, but still I hope to get it faster. I'll try to figure out how to use direct port writing instead of digitalwrite. This is weird for a teensy and not much simple literature. I'll need to really stretch to get it, but i'll post more when I figure out how. Too bad it's not really compatible with the u8glib since at that point it's hardwired for only one specific instance. Any chance of getting HW SPI working for Teensy3?

How do i determine what clockpin and datapin are? Is this SCK and MOSI?

ok, my constructor is using sck pin 13 and mosi pin 11. In the teensy theese are GPIOC pins GPIOC5 and GPIOC6

heres my code

void u8g_arduino_sw_spi_shift_out(uint8_t dataPin, uint8_t clockPin, uint8_t val)
{
  uint8_t i = 8;
  do
  {
    if ( val & 128 )
       GPIOC_PDOR |= (1<<6) ;//  digitalWriteFast(dataPin, HIGH);
    else
       GPIOC_PDOR &= ~(1<<6); // digitalWriteFast(dataPin, LOW);
    val <<= 1;
     GPIOC_PDOR |= (1<<5); // digitalWriteFast(clockPin, HIGH);
    
    GPIOC_PDOR &= ~(1<<5); //  digitalWriteFast(clockPin, LOW);		
    
    i--;
  } while( i != 0 );
}

This ends up being marginally slower than just using digitalWriteFast. Using digitalWriteFast was about 2.1fps and the above code is 1.8fps. any ideas?

Often it is faster to store constant values like ~(1<<5) in a variable. Then you could do loop unrolling.

Oliver

I installed in my car today. The update is much slower than it was on my bench. My signal generator is a higher frequency then either my tach or my Speedometer. I think the frequency that I'm trying to measure is limiting the screen rate. It seemed like when I rev the engine the tach updated quicker. Well this will have to do.

Thank you so much for all your help