Go Down

Topic: Serial Graphic LCD (Read 8628 times) previous topic - next topic

savitch

This is using the Glcd from Sparkfun, a 328 uC, a PCF8563 RTC and a Sharp type IR receiver. The serial version from Sparkfun is cheap enough but still limited by a slower frame rate and function. I used a frame buffer method so the display can be smooth at less than 40ms per frame. The charmap is stored in internal EEPROM and the external EEPROM is used to store bitmaps or screen buffers. It requires at least a 328 because of a 1k frame buffer on top of at least 500bytes variable ram.

This POST screen checks the charmap and a bitmap loaded from EEPROM.


The master program takes over with a menu system.
This is just a quick 7seg style clock to test the RTC read from the slave.


The wires are a little crazy because I didn't expect to use it like this originally and I'm too lazy to rewire.


The schematic pin labels are based on the Duemilanove 328.
http://dl.dropbox.com/u/3647376/blogfiles/GLCD_Serial_Slave.jpg

This is all the source if somebody wants to try this method or maybe find something useful. The main Glcd library also has a shift register option along with extra functions that weren't used for this.
http://dl.dropbox.com/u/3647376/blogfiles/GLCD_serial.zip

designer2k2

nice!

is 40ms the fastest possible?
http://www.designer2k2.at

Caliber Mengsk

O-o

1000/40 = 25
o-O... that should mean 25 fps, which isn't too bad.

savitch

40ms is about the max and it isn't usefull at that speed for any fast movement because the physical panel can't switch on and off fast enough. Usually about 80ms is a good speed for fast movement so the dots have to switch completely.

This is an example using the 3D functions which show it slows to around 75ms and is still a little faster than the display can handle.
http://www.youtube.com/watch?v=oiXdrC8AYUE

The 3D functions are still in the library but not used for the serial setup. It was more just a stupid trick to see what it could do and not that useful. The transform matrix has to recalculate every time the position or rotation changes which is what adds the time. Stationary objects would draw at basically the same speed as a standard line because the matrix is reused.

designer2k2

your video:
[media]http://www.youtube.com/watch?v=oiXdrC8AYUE[/media]

for "standard" applications this is more than fast enough!

http://www.designer2k2.at

mem

I would be interested in seeing the framerate test code, can you post the sketch?

savitch

This is the stripped down version with just the code used for that 3d test. I used an i2c button pad to change rotation.

Quote

#include <Wire.h>
#include <GLCD.h>
#include <GLCDSS.h>

//buttons
int buttons = B0111001;//PCF8574 ID
byte buttonV;//Right,Down,Up,Left,A,B
unsigned long buttonT;

unsigned long framerateT;
unsigned long delay1;

unsigned long dTime;
int dPage=0;

void setup(){
  GlcdS.begin(230400);//set baud rate and start as i2c slave B1011001
  Wire.begin();

//set PCF8574 inputs
  Wire.beginTransmission(buttons);
  Wire.send(255);
  Wire.endTransmission();

  Glcd.Opan.x=Glcd.radian(90);

}

void loop(){
  buttonScan();
  
  if(((buttonV>>0)&1)==0){Glcd.Opan.x+=Glcd.radian(5);Serial.println(Glcd.Opan.x);}
  if(((buttonV>>3)&1)==0){Glcd.Opan.x-=Glcd.radian(5);Serial.println(Glcd.Opan.x);}
  if(((buttonV>>1)&1)==0){Glcd.Opan.y+=Glcd.radian(5);Serial.println(Glcd.Opan.y);}
  if(((buttonV>>2)&1)==0){Glcd.Opan.y-=Glcd.radian(5);Serial.println(Glcd.Opan.y);}
  if(((buttonV>>4)&1)==0){Glcd.Opan.z+=Glcd.radian(5);Serial.println(Glcd.Opan.z);}
  if(((buttonV>>5)&1)==0){Glcd.Opan.z-=Glcd.radian(5);Serial.println(Glcd.Opan.z);}

  Glcd.Opan.y+=Glcd.radian(1);
  if(Glcd.Opan.x>6.27)Glcd.Opan.x=0;
  if(Glcd.Opan.x<0)Glcd.Opan.x=6.27;
  if(Glcd.Opan.y>6.27)Glcd.Opan.y=0;
  if(Glcd.Opan.y<0)Glcd.Opan.y=6.27;
  if(Glcd.Opan.z>6.27)Glcd.Opan.z=0;
  if(Glcd.Opan.z<0)Glcd.Opan.z=6.27;

  Glcd.clearBuffer(0);
  
  Glcd.setObjRot(Glcd.Opan.x,Glcd.Opan.y,Glcd.Opan.z);//panx,pany,panz
  Glcd.setObjPos(0,0,100);//posx,posy,posz
  Glcd.drawCube(0,0,0,32,1);
  Glcd.drawCube(0,16,0,8,1);
  Glcd.drawCube(0,-16,0,8,1);
  Glcd.drawCube(16,0,0,8,1);
  Glcd.drawCube(-16,0,0,8,1);

  Glcd.setLine(0,1);
  Glcd.print((long)(Glcd.degree(Glcd.Opan.x)));
  Glcd.print(" ");
  Glcd.print((long)(Glcd.degree(Glcd.Opan.y)));
  Glcd.print(" ");
  Glcd.print((long)(Glcd.degree(Glcd.Opan.z)));
  Glcd.print(" ");
  Glcd.setLine(1,1);
  Glcd.print((long)(millis()-framerateT));
  Glcd.print("ms");
  framerateT=millis();
  Glcd.drawBuffer();

}

void buttonScan(){
  Wire.requestFrom(buttons,1);
  if (Wire.available()) buttonV = Wire.receive();
}



savitch

I just did a quick test with this code to see what the base frametime is and it shows 6ms. This is filling the 1k buffer with 0 and showing the time then sending it to the screen.

Quote

#include <Wire.h>
#include <GLCD.h>
#include <GLCDSS.h>

unsigned long framerateT;
unsigned long delay1;

unsigned long dTime;
int dPage=0;

void setup(){
  GlcdS.begin(230400);//set baud rate and start as i2c slave B1011001
  Wire.begin();

}

void loop(){

  Glcd.clearBuffer(0);
  Glcd.setLine(0,1);
  Glcd.print((long)(millis()-framerateT));
  Glcd.print("ms");
  framerateT=millis();
  Glcd.drawBuffer();

}



logical1

This is Awesome! The cube is very cool.

Do you know how to get it to rotate about its' own axes? It seems to rotate about some fixed axis that are tied to the plane at this point...You know what I mean???

Thanks again...this is great.

savitch

It's been awhile since I did that but I think I used a fixed camera at 0,0,0 so it only has to calculate a single matrix.

With the camera at 0,0,0 you set the setObjRot and setObjPos to where you want the next object to draw as an offset from the 0,0,0. So set the setObjRot and setObjPos before each drawCube then they will have their own center relative to 0,0,0 and use a different matrix for each one.

logical1

#10
Dec 14, 2010, 10:02 pm Last Edit: Dec 14, 2010, 10:41 pm by logical1 Reason: 1
I think the problem is that all rotations are calculated at once, and do not take into account previous axis rotations...where as if the program first did the x rotation, then the y rotation, then the z rotation taking into account the previous rotation?

I think the current problem is for example first I rotate x by 90 degrees...now the x axis is parallel with the global y axis so if I rotate the global y axis it looks as if I am rotating the cubes about its own x axis again...not its own y axis...so I am still a bit confused on how to go about rotating the cube about its own three axes.

I guess I could keep track of the rotation from axis to axis to axis then use that to figure out the proper rotation....I am not sure...this is still very cool though...Let me know if I missed something here...I just did not understand your explanation I guess.

I just noticed that the x axis behaves properly in all orientations no matter what rotation the other axis are at...and from looking at it you calculated the xy plane last and that seems to make it work properly every time...interesting:)

savitch

Yes, it's only 1 matrix calculation which multiplies all rotations by all transforms at the same time so there isn't any matrix accumulator or extra calcs.  It would need an extra function to multiply a separate rotation matrix before running through the final matrix.

Things start to slow down with all those calcs because every pixel has to run through that matrix. I also tried an external FPU to which speeds it up when there are a lot of matrix calcs. http://www.sparkfun.com/products/8129


logical1

#12
Dec 14, 2010, 11:37 pm Last Edit: Dec 14, 2010, 11:54 pm by logical1 Reason: 1
I don't care if it gets choppy I am just kinda interested in the process of keeping track of the vertices in 3d space. Very cool stuff. Well I will keep looking around...

I tried summing the previous matrix with the new matrix but that did not help...it made it worse...although it did make some pretty funny spinning orbit things...but not very useful things were blowing up and spinning out of control...

So perhaps I need to...
1.run the calculation for the xy plane last (like you did here)...and use only the x values from the resulting matrix in the output matrix as the x values

2. run the calculation for the yz plane last (switch yours around a bit)...and use only the y values from the resulting matrix in the output matrix as the y values


2.run the calculation for the xz plane last (switch yours around a bit)...and use only the z values from the resulting matrix in the output matrix as the z values


or perhaps this is stupid...I will try it anyways....that did not seem to work:/

The shape gets augmented when at weird angles.

savitch

It's a little confusing at first but the transform matrix is multiplied together, not added. There are really only 2 things you need to get straight to understand all these 3d transforms.

The first is to make sure you understand is matrix multiplication which is easy but looks complicated at first glance.
http://www.mathwarehouse.com/algebra/matrix/multiply-matrix.php

Then you can see how it relates to 3d transforms.
http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/2d_3d_xforms/

Everything starts with a 3x3 identity matrix, then each translation is multiplied together to end up with the final matrix that will translate each point.

logical1

Yes I have also tried to do this the same way that is explained in that article, and it runs into the same problem...only the last axis to be multiplied rotates about its own axis in their case...and most I have seen it is the z axis
Quote
3D transforms

All transformations directly extend to 3D
Translation:
                     | 1 0 0 dx |

T(dx,dy,dz) =  | 0 1 0 dy |
                     | 0 0 1 dz |
                     | 0 0 0 1  |

Scaling:
                     | sx  0  0  0 |

S(sx,sy,sz) =  |  0 sy  0  0 |
                    |  0  0 sz  0 |
                    |  0  0  0  1 |
Rotation:
           | 1      0        0   0 |
Rx(A) = | 0  cos A   -sin A   0 |
            | 0  sin A    cos A   0 |
            | 0      0        0   1 |

          | cos A   0   sin A   0 |
Ry(A) = |     0   1       0   0 |
           | -sin A  0   cos A   0 |
            |     0   0       0   1 |

           | cos A  -sin A   0   0 |
Rz(A) = | sin A   cos A   0   0 |
            |     0       0   1   0 |
             |     0       0   0   1 |


This code only rotates the cube properly in the z direction if the matrices are multiplied in the order shown above....Now I say properly....but I only mean properly in the sense that the input rotation angles affect the rotation of the cube according to its own axis not the axis of the world it is in...so if someone was only interested in the current rotation this would be fine...I am just trying to get it to work in this particular way. Anyways let me know if this is annoying...I can stop posting...I was just curious if there was a fix for this issue. Thanks again for your time.

Go Up