Serial Graphic LCD

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

nice!

is 40ms the fastest possible?

O-o

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

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.

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.

your video:

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

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

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

#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();
}

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.

#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();

}

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.

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.

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:)

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. Floating Point Co-Processor uM-FPU v3.1 - COM-08129 - SparkFun Electronics

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

  1. 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.

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.

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.

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

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.

The camera is looking in the Z direction so that's why it seems to be rotating on its own axis, it's still in line with the camera Z axis. The order everything gets multiplied is very specific so apply all rotations first, then the translation. Usually the order will seem backwards to what you actually want to do.

Yes I agree if I translate the object before I rotate it, it ends up rotating about the center 0,0,0 like the moon around the earth instead of rotating along the axes...probably useful for something...but i just want to be able to rotate the object about its own axes.

I think I am going to have to just keep track of the orientation of the cube, and just add in angular increments to rotate the object from its current position...then store it again and so on...because if I try to calculate the rotation from 3 "finished" angles, then the order in which the rotations occur affects the outcome...so if I calculate x,y, then z and say they all rotated by 90 I would end up in a completely different orientation then if I calculated them z,y,x...accept for a few special cases of course.

I just can't think of a good way to determine the axes of rotation once the cube has been rotated already...I mean I can keep track of the new vertices of the rotated cube, but then I have to figure out how to rotate about the new angles that the axes are currently aligned with....