Cat toy (2 servos) - how to handle data

Subject: Cat toy (2 servos) - how to handle data
Project Objective:
To learn about the arduino by creating a interactive cat toy.

Vid of project to date

Method:
use 2 servos that move a stick on a flat 2D plane ("x" and "y") with a squirrel tail dangling from it.
I have divided the action into discrete tasks which are comprised of multiple steps where I define the end goal as x, y and define how long it is to take to get there (, , ).

The Problem:
I am not very skilled at programming, and have run to my limit on what I can solve with Google. I am currently stuck on how to define each task. At the moment I have statically defined 10 tasks that consist of 10 steps each. This is ok as a proof of concept but lacks the flexibility to grow this project to the next level. Ideally I would like to have the flexibility to have the sketch read values from a file (defining tasks on a spreadsheet would be so much nicer) and create the correct number of tasks that consist of a varying number of steps.

Projects future development:
If I figure out the above issues, I would then like to start to experiment with using various sensors that will trigger different tasks. If all goes well, I'm then hoping to learn how to make my own pcb and create a permanent gadget.

Hardware:
-Arduino Duemilanove
-2x Power Sources:
--->USB from computer to drive Arduino
--->Portable USB power(batt running through a regulator). I added a cap to smooth it out a little
-2x standard sized servos
-breadboard (because I hate soldering stuff)

EDIT
I had to delete Code because it causes post to be larger than max char allowed.

HERE IS CODE

Ideally I would like to have the flexibility to have the sketch read values from a file

This is possible, if the file is on an SD card, and you have an SD shield.

defining tasks on a spreadsheet would be so much nicer

Than what? Being poked by sharp objects?

and create the correct number of tasks that consist of a varying number of steps.

How? What would the data in the file look like? How would the "correct number of tasks" be determined? How would the "varying number of steps" (per task?) be determined? Would the number of steps really be varying, or would the number of steps to get a task done be what varies?

I don't do google docs, and I see no particular reason to look at your code, since you didn't ask any questions about it.

Thanks PaulS for your response. Let me try and address your comments to help clarify things for you.

Ideally I would like to have the flexibility to have the sketch read values from a file

This is possible, if the file is on an SD card, and you have an SD shield.

It seems to me to be real messy coding (not to mention not very user friendly) if I have to code in each variable in setup() as I am currently. Imagine having to type all the following a few hundred times:

Task[0].Step[0].xPos = 5;
 Task[0].Step[0].yPos = 90;
 Task[0].Step[0].TimeToComplete = 1000;

I am thinking if I define the three fields in a spreadsheet and save them as text it would be a slicker method. If saving a dat or txt file on arduio is not possible I imagine I could just declare it as a string. Something like this:

//data format: <qty of steps in task>,<x>,<y>,<TimeToCompleteStep>,<x>,<y>,<TimeToCompleteStep>,…etc…
string DataString = “7,14,32,11000,170,155,7000,…etc…

not sure if string has a size limit… if it does I’m back to the drawing board.

defining tasks on a spreadsheet would be so much nicer

Than what? Being poked by sharp objects?

Lol, not sure what to say… think I delt with it above ;^)

and create the correct number of tasks that consist of a varying number of steps.

How? What would the data in the file look like? How would the "correct number of tasks" be determined? How would the "varying number of steps" (per task?) be determined? Would the number of steps really be varying, or would the number of steps to get a task done be what varies?

At the moment I have an array of an array of records. Let me show you my defining it:

typedef struct{
 int xPos;  //define ending x position
 int yPos;  //define ending y position
 unsigned long TimeToComplete; //define length  of time to reach ending position (sets speed of servo)
} TStep;

typedef struct{
 TStep Step[10];
 int LastStep;
} TTask;

TTask Task[10];

It would be very nice if there was some way to make these arrays dynamic (created during runtime)

I don't do google docs, and I see no particular reason to look at your code, since you didn't ask any questions about it.

And now you don’t have to… :smiley:

Thanks again for taking the time to look and respond so quickly.

I am thinking if I define the three fields in a spreadsheet and save them as text it would be a slicker method.

OK.

If saving a dat or txt file on arduio is not possible

On the Arduino, no. On an SD card, yes.

I imagine I could just declare it as a string.

Why? Then, you need to parse the string, and convert each token to an int. The compiler already knows hoe to do that, and does it at compile time, not run time. Use a struct with int fields. Create an array of struct instances.

Oh, wait, you're already doing that. I don't see where you initialize the Task array, though.

SD card readers are relatively cheap, and very easy to work with. Plug them in, and treat the thing like a hard drive.

It seems to me, though, that you might be over-thinking this. If you are developing an XY plotter that needs time to plot with differing inks, then your approach is ideal. For a cat toy, random motions seem more logical.

For a cat toy, random motions seem more logical.

No not aiming for random motions but rather need to call up specific tasks with multiple steps that have very accurate x/y targets and set length of time to get to that point. Yes, this is currently a cat toy, but in reality it is a practice run for a future project where most of this code will be re-tasked. If you watched the vid I posted, the cat toy was just the hook for my 7 year old daughter so she would take an interest in an electronics project (with a bonus intro into video editing).

So back to the original problem, is it possible to create dynamic arrays whose length (number items in the array) is set during runtime?

If you watched the vid I posted

Well, I couldn't, because the site is blocked at work.

So back to the original problem, is it possible to create dynamic arrays whose length (number items in the array) is set during runtime?

Of course. If you are very careful. There is a limit on how much memory the Arduino has (depending on which Arduino you have).

If you are going to re-purpose the code, I'd suggest either a SD card to save the large amounts of data, or a serial connection to have the PC send the data one step at a time.

could you please give an example as I have not had any luck with using "new"

could you please give an example as I have not had any luck with using "new"

How have you used it? You can also use malloc() and free().

From your video I see that you do not have a completely wrong idea of a microcontroller.
For anyone else:
An Arduino UNO e.g. has 2048 bytes of RAM, which are used for all variable data, both stack and heap.
512 byte RAM is also a common size for smaller controllers.

Fortunately code does not run in RAM, and the 32kB of Flash memory are rather plenty. With a little trick, you can keep constant data in that flash memory.

Additionally, a microcontroller starts at power up or reset, and runs the little code in flash memory forever, in an endless loop.
As the same code will run again after a few microseconds, there's no need to free memory dynamically, and thus you don't need to allocate dynamic memory neither. ( Agreed, one can argue on this, but I hope one gets the point )
Be happy if you have enough RAM for your array ( No one tells you at run time, BTW ...)
Neither new nor malloc() is too useful.

As you have tasks that are controlled by dynamic parameters, you can sure get those parameters from an SD card as needed.
You might add parameters saying "modify by sensor value" or adding random data.

A half way reasonable use case for new were to build a chain of Tasks ( instead of a fixed size array ), each having a pointer to the next Task, until

** **task.next = new Task();** **
would return a 0, indicating that memory is full. In that case you instead insert the address of the first task and have a ring of the max possible length of tasks.

In that case you instead insert the address of the first task and have a ring of the max possible length of tasks.

Until you call a function, which requires pushing arguments onto the stack, for which there is no room...

for which there is no room...

... and no way of run time error handling.

Agreed, no new nor malloc().

Or:
Do that inside a function which has defined a local byte blocker[300]; variable.
Anyone volunteer to test if malloc() really works ok when it reaches stack ?

Or:
Test if that pointer remains unmodified at run time

Or:
Any other suggestion ...

Simple two servo test code. You can defeat the arduino auto reset with a 100 ohm resistor, and make a simple repeating batch file to operate the servos via the pc serial port.

// zoomkat 11-22-10 serial servo (2) test
// for writeMicroseconds, use a value like 1500
// for IDE 0019 and later
// Powering a servo from the arduino usually DOES NOT WORK.
// two servo setup with two servo commands
// send eight character string like 15001500 or 14501550

#include <Servo.h> 
String readString, servo1, servo2;
Servo myservo1;  // create servo object to control a servo 
Servo myservo2;

void setup() {
  Serial.begin(9600);
  myservo1.attach(6);  //the pin for the servo control 
  myservo2.attach(7);
  Serial.println("servo-test-21"); // so I can keep track of what is loaded
}

void loop() {

  while (Serial.available()) {
    delay(1);  
    if (Serial.available() >0) {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
    } 
  }

  if (readString.length() >0) {
      Serial.println(readString); //see what was received
      
      // expect a string like 07002100 containing the two servo positions      
      servo1 = readString.substring(0, 4); //get the first four characters
      servo2 = readString.substring(4, 8); //get the next four characters 
      
      Serial.println(servo1);  //print to serial monitor to see results
      Serial.println(servo2);
      
      int n1 = servo1.toInt();
      int n2 = servo2.toInt();
      
      myservo1.writeMicroseconds(n1); //set servo position 
      myservo2.writeMicroseconds(n2);
    readString="";
  } 
}

Below is the looping batch file you can test with when the arduino auto reset is defeated. Copy the code, paste in notepad, and save on the desktop as servoloop.bat. This is set for comport 3 at 9600 bps. Double click (or right click and run) the servoloop.bat file to run.

@echo off
mode com3:9600,N,8,1 >nul
echo moving servos
echo 07001500 > com3 
echo 8 second delay
ping -n 9 127.0.0.1 >nul 
echo 22000700 > com3 
echo 5 second delay
ping -n 6 127.0.0.1 >nul 
echo 15001500 > com3
echo 5 second delay 
ping -n 6 127.0.0.1 >nul 
echo 09001800 > com3
echo done
echo Did it work?
pause
servoloop.bat