Optical mouse sensor & stepper motors & oled

Hello

I have a setup with optical mouse sensor, stepper motor & oled display.

My problem is that, when i use the stepper motor or display it slows the whole program down so much that the optical mouse sensor will overflow.

It has a maximum values of +128 and -127. When i have just the optical mouse sensor running, it works fine. Its fast enough to read fast movement without overflow.

But if i put if i input something to the OLED. It will slow the program so much, that the mouse sensor will overflow on fast movement. The same goes for the stepped motor.

Any ideas how to approach a problem like this.

I also tested this on Teensy 3.2, and the speed of the board does not seem to make any difference on this matter.

The mouse sensor is ISP, oled I2C and a tiny stepper motor ran straight from the arduino nano (have worked well so far)

I need to move the stepper moved based on the output of the optical mouse sensor. And at the same time output some simple data to the OLED. The main thing is, that the mouse sensor should be 99.99% accurate.

It could be the I2C bus that is slowing things down, it runs relatively slowly at 100Khz. Moreover the Wire library is blocking so waits for the I2C action to complete.

I'm pretty sure you can increase the speed of the I2C to 400Khz but that may be only for a Mega not a UNO but even so may not be fast enough.

Perhaps someone here knows of either a way to speed up I2C (so the LCD still works) or a non-blocking Wire library replacement?

BTW you can test this theory by commenting out the LCD commands (ie not send anything to the LCD and see if the mouse works properly).

monkeyfist:
it slows the whole program down so much

What program?

Post the program so we can see what you can see.
And please use the code button </>so your code looks like thisand is easy to copy to a text editor

…R

Ralph_S_Bacon: It could be the I2C bus that is slowing things down, it runs relatively slowly at 100Khz. Moreover the Wire library is blocking so waits for the I2C action to complete.

I'm pretty sure you can increase the speed of the I2C to 400Khz but that may be only for a Mega not a UNO but even so may not be fast enough.

Perhaps someone here knows of either a way to speed up I2C (so the LCD still works) or a non-blocking Wire library replacement?

BTW you can test this theory by commenting out the LCD commands (ie not send anything to the LCD and see if the mouse works properly).

Hello

Yes, i have tested this by running just the mouse sensor.

Then the mouse sensor with OLED.

And the mouse sensor just with stepper motor.

I assume its not the I2C oled, as the stepper motor also gives the same problem.

I´m thinking if there is a way to buffer the data coming from the mouse sensor, but even this might not help as it does not read it fast enough. The max buffer of the mouse sensor is the +128 or -127.

Then i could also maybe but it in 45degree angle, and read both X and Y, thus getting basically double the pixels. But this would be hard, as the sensor should be pretty much exactly in 45 degree angle.

I'm using the mouse sensor for measuring distance, and i need it to be as accurate as it can be.

Robin2:
What program?

Post the program so we can see what you can see.
And please use the code button </>

so your code looks like this

and is easy to copy to a text editor

…R

Hello

Here is my simple test version, it reads the mouse sensor and puts some text in the OLED randomly.

In the actual code i’m just drawing a rectangular on the screen, that does not move as much. But the problem is the same.

The program also outputs serial data from the mouse sensor.

//Add the ADNS2620 Library to the sketch.
#include <adns2620.h>

#include <Adafruit_GFX.h>      // näyttö
#include <Adafruit_SSD1306.h>  // näyttö

//Name the ADNS2620, and tell the sketch which pins are used for communication
ADNS2620 mouse(12,13); // 14 ja 15 teensyllä
Adafruit_SSD1306 display(4); //#define OLED_RESET 4  Näytön pinnit ovat PINNIT A4 (SDA) ja A5 (SCK)

//This value will be used to store information from the mouse registers.
int8_t valueX=0;
int8_t valueY=0;
int positioX=0;
int positioY=0;
float mmY = 0;
float mmX = 0;
unsigned char value1=0;
int joku = 0;
int joku1 = 0;

                                                                                                             
void setup()
{
	//Initialize the ADNS2620
   mouse.begin();
   delay(100);
	//A sync is performed to make sure the ADNS2620 is communicating
   mouse.sync();
	//Put the ADNS2620 into 'always on' mode.
   mouse.write(CONFIGURATION_REG, 0x01);
   delay(100); 
   display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
   //Create a serial output.
   Serial.begin(9600);
   
}

void loop()
{
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(random(1, 50),random(1, 50));
  display.print("jou jou jou");
  display.display();

   joku = mouse.read(SHUTTER_UPPER_REG);  // sulkimen nopeus, pienempi parempi. näyttäis että 5 arvo jo antaa tarkan lukema nopeista liikkeistä
  
   joku1 = mouse.read(SHUTTER_LOWER_REG);
 
   valueY = mouse.read(DELTA_Y_REG);  // Ylös alas liike
   valueX = mouse.read(DELTA_X_REG);

   value1 = mouse.read(SQUAL_REG); // pinnan laatu 0-255, 100 tai yli on ok
 
   //valueY=0-valueY;
   valueX=0-valueX;
  
   positioX=positioX+valueX;  // laske liike
   positioY=positioY+valueY;  // laske liike
   
	 mmY=positioY * 0.06;  // muutta liike millimetreiksi
   mmX=positioX * 0.06;  // muutta liike millimetreiksi
   
	 Serial.print("SHUTTER_UPPER_REG:");
   Serial.print(joku);
   Serial.print('\t');
   Serial.print("SHUTTER_LOWER_REG:");
   Serial.print(joku1, HEX);
   Serial.print('\t');
   Serial.print("Y:");
   Serial.print(valueY, DEC);
   Serial.print('\t');
   Serial.print("X:");
   Serial.print(valueX, DEC);
   Serial.print('\t');
   Serial.print("PositioY:");
   Serial.print(positioY);
   Serial.print('\t');
   Serial.print("PositioX:");
   Serial.print(positioX);
   Serial.print('\t');
   Serial.print("Positiot/2:");
   Serial.print((positioX+positioY)/2);
   Serial.print('\t');
   Serial.print("Surface Quality:");
   Serial.print(value1);
   Serial.print('\t');
   Serial.print("Y mm:");
   Serial.print(mmY);
   Serial.print('\t');
   Serial.print("X mm:");
   Serial.println(mmX);


delay(5);    // ei välttämätön

    if (Serial.read() == 'x') // x nollaa
    {
      positioX=0; 
      positioY=0; 
     }
}

I don't see any stepper code in your program.

I do see an enormous amount of time-wasting printing and displaying.

You should not be printing or displaying in every iteration of loop(). Once or twice per second should be sufficient. And you should probably not do the whole print or display in a single action. Taking 2 or 4 smaller bites would mean that the printing would present less of a delay.

Making a stepper motor move one step should not interfere significantly with the repetition speed.

These links may be helpful Several Things at a Time Simple Stepper Code Stepper Motor Basics

...R

Robin2: I don't see any stepper code in your program.

I do see an enormous amount of time-wasting printing and displaying.

You should not be printing or displaying in every iteration of loop(). Once or twice per second should be sufficient. And you should probably not do the whole print or display in a single action. Taking 2 or 4 smaller bites would mean that the printing would present less of a delay.

Making a stepper motor move one step should not interfere significantly with the repetition speed.

These links may be helpful Several Things at a Time Simple Stepper Code Stepper Motor Basics

...R

As i said, this is a test program.

This does not include the stepper motor part. I have another test file for that. This is just the mouse sensor & OLED.

The serial printing does not slow it down, as if i do not print anything to the OLED its plenty fast.

I see your point about the stepper motor, i need to create a buffer for it and move it only few steps per loop. Currently im trying to move it as the mouse sensor moves, so max 127steps per loop. I'll make some sort of variable to control how many step per loop it can move max, so i can test what will work.

Also in this example, i know im printing too much into the OLED. In the actual code im printing a square that moves a bit according to the mouse sensor data. But it does not move much, still it seemed to slow the program down too much for the mouse sensor to overflow.

Maybe this would be corrected by switching to an faster ISP OLED, istead of the I2C.

But i´m also interested in how could i make the OLED printing fast, should i print the square in parts? Like one line per loop?

I tested switching from text to just drawing one random pixel per loop, it´s still too slow, even if i take the clearDisplay of the loop and just let the pixels stay on.

I dont have a pullup resistor in the I2C line, i have read that i should maybe have one. Could this affect the speed so much?

To overflow the sensor, it needs to move 5.4mm this equals 128dots. At 600dpi.

monkeyfist: and move it only few steps per loop

ONE step.

And it probably will not actually need to make a step every iteration of loop()

Like one line per loop?

I have no experience of those devices but that is certainly what I would be thinking of.

...R

Robin2: ONE step.

And it probably will not actually need to make a step every iteration of loop() I have no experience of those devices but that is certainly what I would be thinking of.

...R

Ok, thanks for this. I had not thought about the whole loop thing. This was just the type of thinking i was looking for. I will start testing this with the step motor.

If anyone has any experience about I2C OLEDS, do give some input.

Currently even drawing one pixel per loop slows it too much for the mouse sensor to overflow. Is this just the slow speed of I2C, lack of pull up resistor or something else?

There must be something wrong, as I´m able to move the sensor 5.4mm in timespan of one loop, this sounds really weird. And i'm hoping to use more accurate ADNS 5050 sensor next.

monkeyfist: Currently even drawing one pixel per loop slows it too much for the mouse sensor to overflow. Is this just the slow speed of I2C, lack of pull up resistor or something else?

Post the program that demonstrates that.

...R

Do what Robin2 suggests but also note that you have a 'clear' command in your main loop.

In the datasheets I have for I2C LCD displays it states clearly that clearing the display takes many tens of milliseconds whereas writing a single dot takes microseconds.

Try taking that out of your main loop (or read the datasheet and confirm to your own satisfaction about the speed of clearing the display).

Ralph_S_Bacon: Do what Robin2 suggests but also note that you have a 'clear' command in your main loop.

In the datasheets I have for I2C LCD displays it states clearly that clearing the display takes many tens of milliseconds whereas writing a single dot takes microseconds.

Try taking that out of your main loop (or read the datasheet and confirm to your own satisfaction about the speed of clearing the display).

Hello

I did take the clear off of it, noted it earlier, the example program is the same as the one i posted earlier. Just switched the:

display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(random(1, 50),random(1, 50));
  display.print("jou jou jou");
  display.display();

Part to simply draw one random pixel:

  display.drawPixel(random(1, 128),random(1,65),WHITE);
  display.display();

Every time i use the display.display(); the program freezes enough that the mouse sensor can overflow. I can display.dawpixels as much i like. But refreshing the display is what makes the program stall.

I also tested the step motor, and can do at least 5 step per loop. This yielded enough fast movement in the motor, and no overflow. Single step was way to slow, and 10 gave overflow.

I can then just start reading the mouse sensor multiple times per loop, so i will read it again after the step motor movement, before OLED update. If i can get the OLED to work fast enough.

So i think what i´m doing is doable, if i get the OLED working faster.

I timed the one pixel loop, takes 40ms.

First I was reading 5 registers from the mouse sensor, this way it took 43ms. With just the one registry i need read, takes 40ms. And if i do not draw any pixels on the OLED, 6-7ms. The mouse sensor is really fast to read.

I also tested with delay, that i can have about 25ms delay between mouse sensor reads. So i´m about 7ms too slow currently when i draw just one pixel and there is no step motors or anything else in the loop.

Maybe the Adafruit library is just really slow.

Seems my timings are about the same as posted here, ill start looking into this. Seems it is doable.

http://forum.arduino.cc/index.php?topic=286837.0

Thanks for the idea of timing, now i know about what i need and how much time i got to do it.

If anyone knows some ready made library/solution to fast I2C OLED update, please let me know. Im not a marvel in coding :) My background is in QBasic 4.5 in the 90´s :)

What of Reply #9 is hard to understand?

...R

Robin2: What of Reply #9 is hard to understand?

...R

What of "the example program is the same as the one i posted earlier. Just switched the:" is hard to understand.

Don´t be a dick. I know its the usual forum way. But please do not be one. I appreciate your help, but i have low tolerance for dicks.

The actual problem seems to be in the way the adafruit library works, it sends the whole display buffer. Even if i only draw one pixel. Or even if i do not draw anything at all.

Just saying display.display() takes 39ms. Even if i do not draw anything at all to the display. So drawing something is not the problem, problem is the time it takes to send the whole display buffer to the OLED.

Breaking the rectangle in parts using adafruit lib would not speed things at all. It would probably actually slow things down.

Switching to u8lib & ISP OLED should speed things up just enough for this to work.

According to this video, I should get 22ms update speed on u8lib & ISP OLED:

https://www.youtube.com/watch?v=lkWZuAnHa2Y

Speeding this more than that, i don't know. Everything i seems to find talks about characters, not lines or rectangles like i need. Optimally i would like to get down to something like 10ms, this way i could raise the mouse sensor DPI to 1000DPI, and still catch fast movement accurately.

So currently i could make this work like this, by switching to ISP u8lib driven OLED:

read mouse sensor move motor 5 steps read mouse sensor again update OLED

monkeyfist: but i have low tolerance for dicks.

Not as low as I have.

This is the 3rd and last time of asking. Please post the program that demonstrates the problem I quoted in Reply #9

...R

Robin2: Not as low as I have.

This is the 3rd and last time of asking. Please post the program that demonstrates the problem I quoted in Reply #9

...R

Hello

I already did post it. It is the same program, with the one change that i posted.

And i have also already located the problem, as i wrote in the last post. The problem is the slow update speed of I2C combined with Adafruit libs way of sending the whole display buffer regardless of what you draw on it, if anything. It's 39ms, even if i do not draw anything on the display.

Ralph_S_Bacon helpful advice to time things led me to realize this.

And the update speed i measured is the same that everyone else seems to get. You can see the youtube & forum links i posted.

I ordered a ISP OLED, and will be switching to u8lib. This should speed things to manageable 22ms update speed. But i wrote all this allready. After that i will see if there is some way to make it faster than that. The faster i can get this, the more i can raise my mouse sensors DPI value. I would like to get to 0.03mm accuracy. Currently I´m at 0.06mm at 600pdi.

The other way of dealing this, would be to use some sort of absolute encoder instead of the mouse sensor. That could not skip any information, even if i could not read it enough fast. I kinda like the mouse sensor, as it can measure any surface. And does not need any mechanical contact.

Or make it more complicated, and add a dedicated microcontroller for the mouse sensor that would keep reading the mouse sensor & store the data & send it to the arduino. But i rather keep this as simple as i can. As this is my first attempt at arduino.

At first i used a potentiometer, but the noise is too much. I cant have any noise.

monkeyfist:
I already did post it. It is the same program, with the one change that i posted.

If you mean the program in Reply#4, I can’t see where that demonstrates

Currently even drawing one pixel per loop slows it too much for the mouse sensor to overflow

…R