I am automating a six foot diameter cylinder that has 584 photographs on it (laid up in spiral around the cylinder). To the side of the cylinder is a vertical actuator on which a projector is mounted. By turning the cylinder and raising/ lowering the actuator I can access any and all of the photographs to be projected on the wall. I have the cylinder and actuator motors under control, homing and reporting their positions with encoders. All is good there.
Now I want to be able for the user to type in number of a specific photograph and the machine move to that position.
I am wonder what the best way of storing all the photographs' positions on the Arduino Uno. If I use an array in the program, it will be a PITA to edit the numbers as formatting in the IDE isn't that great. Will I gobble up all the UNO's memory with 584 coordinates (rotary and vertical positions)?
If I go with a SD card is there a way to access a specific photograph's coordinates? For example, can I recall the coordinates of photograph # 273? Does the CVS file get dumped into an array anyway? I couldn't easily tell from SD explanations. It's a lot easier editing the numbers in Excel and I can graph the coordinates to make sure they are reasonable.
Adressing 584 positions need some data space. How many bits/bytes do You need to adress one picture? The UNO has a limited amount of RAM so using a conversion- /look up- array looks hard to create. One way could be a giant switch-case construction where the position is hard coded in the sketch.
Maybe another Arduino then an UNO would be better.
Bricoleur:
If I use an array in the program, it will be a PITA to edit the numbers as formatting in the IDE isn't that great.
You can use any program you want to format the array. You could even put it in a separate .h file (e.g. PhotoPositions.h) and then add an #include directive to the sketch:
#include "PhotoPositions.h"
Bricoleur:
Will I gobble up all the UNO's memory with 584 coordinates (rotary and vertical positions)?
You might have more free program memory than dynamic memory. If so, you can put the array in program memory using PROGMEM:
pert:
You can use any program you want to format the array. You could even put it in a separate .h file (e.g. PhotoPositions.h) and then add an #include directive to the sketch:
#include "PhotoPositions.h"
You might have more free program memory than dynamic memory. If so, you can put the array in program memory using PROGMEM: PROGMEM - Arduino Reference
This is an interesting idea! I still could edit the numbers off of the Arduino IDE in Excel then save it as a CSV then as a .h file.
Railroader:
Adressing 584 positions need some data space. How many bits/bytes do You need to adress one picture? The UNO has a limited amount of RAM so using a conversion- /look up- array looks hard to create. One way could be a giant switch-case construction where the position is hard coded in the sketch.
Maybe another Arduino then an UNO would be better.
I have 584 positions with two encoder vales (one of around 4000 pulses and the other around 1000 pulse). Not sure how much memory that would require. Does the MEGA have more data storage memory?
jimLee:
Are they the same size? Is there a pattern to their layout? Can't you come up with a formula picture(X) = fa(X),fb(X)? Then you don't store anything.
-jim lee
The photos are the same size but their positions, unfortunately, aren't as uniform. This would be a great way of tossing out the memory problem but I think I need to brute force these positions with known encoder values. Rats!
Incidentally, these photos came out of an abandoned drug store that had its own film processing lab. Vintage and classic 1970 shots! The photos were still on long strips of paper and never cut to size. These were scanned, edited for color then finally printed on a huge sheet of paper to make the cylinder.
Both pert and hammy thinks outside the box and their suggestions are really usable. Are all the pictures of the same size? Then You could think of a horizontal distance being a constant and each picture being moved down vertically the amount of steps needed to make the second lap of pictures start below the first picture.
I worked on a machine that did a rough alignment first, then looked at what it aligned on. From that calculated an offset for final alignment. Maybe you could do something like that? Find a corner then move to an edge?
Bricoleur:
This is an interesting idea! I still could edit the numbers off of the Arduino IDE in Excel then save it as a CSV then as a .h file.
I think that's a good idea. Even if you needed to manually edit the file to add a couple lines at the top and bottom to make it a valid C++ array, that would be easy enough.
I've done something like that when I needed to make sure some control codes were synced between a program running on Arduino boards and a Python program running on my computers. I put them in a spreadsheet and then set it up so that I could easily generate the .h file and the python code from it. I didn't fully automate it since it was not going to change so frequently as to be worth the effort but that could have easily been done.
In your case, it wouldn't be anywhere near so complicated.
Railroader:
Both pert and hammy thinks outside the box and their suggestions are really usable. Are all the pictures of the same size? Then You could think of a horizontal distance being a constant and each picture being moved down vertically the amount of steps needed to make the second lap of pictures start below the first picture.
The other bugaboo is that the projector needs to be spot-on to the photos as the lens distorts the photos a little bit. I had thought about the consistency of the stack of photos but they are just enough off to make a formula not the best choice. I would program the movement that way in a heartbeat but I need to be a bit fussy about the placement of the cylinder. My home position's are very repeatable (as they should!) and rock solid.
The photos are laid up in spiral, which isn't a problem to locate, but the photos were plopped down in an uneven way.
sterretje:
Each position is two integers (0..1000, 0..4000), so roughly 2.5 kByte of PROGMEM needed for 500 plus photos.
Regarding the question about the sd card, if you store the data in records with a fixed width, you can easily access each record using a seek.
I just ordered an SD card shield and will try that. My client is also thinking about a small TFT touchscreen for entry and info about a specific photo. Hope the SD card and TFT don't interfere with each other though I know you can get a TFT screen with an SD card on it. Here I go!
That's the one. I've used it before and it works great - colors are rich. I am also switching to a MEGA as I am running out of interrupt pins with the UNO. Also, a switch to a MEGA because the TFT scoops up a lot of pins.
My current goto for a processor is the teensy 3.2. Tons of horsepower & 64k of RAM. All in a package about the size of my thumb. The RAM comes in extremely handy when you start messing about with color displays.
sterretje:
Each position is two integers (0..1000, 0..4000), so roughly 2.5 kByte of PROGMEM needed for 500 plus photos.
Regarding the question about the sd card, if you store the data in records with a fixed width, you can easily access each record using a seek.
I'm inching closer to my goal! I was able to write coordinates onto a SD card then read it directly. I used the SEEK() function and can get the values of each digit in CSV files but what I would like is the entire number(s) separated by the comma. Do I need to brute force these individual numbers to get the whole thing? For example. If my coordinate is (125, 647), would I need to push the SEEK () along this string and add them up like 1X100 + 2X10 + 5X1 ? There must be an easier way to get the first 4 bits into a number. Examples of SD card manipulation are pretty sparse!
The seek() works if the records are fixed width, so you need to guarantee that. It is used to quickly go to a record.
Next you simply read a line by reading from there to the newline character if it's text based (as your csv)'
If you use a text based csv, do a search for Robin2's serial input basics thread. The principles of reading a sd card or reading a serial port don't differ. It also contains a parse example to split on the comma.
Bricoleur:
I'm inching closer to my goal! I was able to write coordinates onto a SD card then read it directly. I used the SEEK() function and can get the values of each digit in CSV files but what I would like is the entire number(s) separated by the comma. Do I need to brute force these individual numbers to get the whole thing? For example. If my coordinate is (125, 647), would I need to push the SEEK () along this string and add them up like 1X100 + 2X10 + 5X1 ? There must be an easier way to get the first 4 bits into a number. Examples of SD card manipulation are pretty sparse!
You use a text file when block data is the far better choice. For one, block data does not have to be read and evaluated into variables since the data is the contents of the variables. You read 2 bytes and write them into an int, there's a coordinate. 1st picture coord pair is the 1st 4 bytes of the block file, 2nd picture is the next 4, etc.
If the pictures are not going to change then you're better off storing the data in PROGMEM and certainly magnitudes faster. You'll have one less device to go wrong or even just to power.
If you want text data for each picture... the Mega2560 has 256K flash and your code will likely be < 10K, you have a lot of room.