Deep Think Project - Artificial Intelligence Research Project

Regards,
Ray L.

Your multiple, multiple gotos seem to be doing this:

  while(Time() != 1) {
    //wait
  }

If you get just one of those WLAT1 labels wrong or copy-paste a bit of code without thoroughly checking all the labels inside it then lots of aparrently random things will happen.

My code snippet can be pasted anywhere into the code and it won't jump to a random label elsewhere in the code. That's why gotos are bad.

It is still the wrong way to do it. If you need a delay and there is absolutely nothing else that you program needs to do at the same time, then just use the delay() function. "Waiting for motors to calibrate" is a good example where delay should be used.

Is this better? MorganS, the answer is that I intend to have other things going on, but not just yet. I am working on getting the servos to work right now, but it makes sense to go ahead and write a non-blocking version of delay() because in the near future I will add sensors to the code. I would like to implement multitasking in the near future.

//
// Deep Think 0.0.0.2
//
// programmed by George Andrews
//
// NOTE: This program is designed for the Meccanoid G15 (combined
// with the 86Duino One). It is a part of the Deep Think Project
// (first version of the software for the project). The Deep Think
// Project is designed to advance the intelligence (as well as
// motion and structural capabilities) of humanoid robots. This
// version of the program is designed to do the following.
//
// 1. Perform various moves using functions.
// 2. Control the 2 D/C motors with the 86Duino.
//
// Please note that this version is only intended as a demo to
// establish a basic framework for interfacing the Meccanoid
// electronic parts with the 86Duino One for future development.
// This version of the software, however, has the following
// additional capabilities compared to the previous version Deep
// Think 0.0.0.1.
//
// 1. Can interface with the D/C motors as well as the servos and
//    LED eyes.
// 2. Can perform various moves using functions in the program.
//

#include "MeccaBrain.h"

//
// Variables
//

// pin declarations
int LeftArmDaisyChainPin = 21;
int LEDEyePin = 29;
int RightArmDaisyChainPin = 38;
int LeftFootDCMotorPin = 11;
int RightFootDCMotorPin = 13;

// class objects
MeccaBrain LeftArmDaisyChain(LeftArmDaisyChainPin);
MeccaBrain LEDEye(LEDEyePin);
MeccaBrain RightArmDaisyChain(RightArmDaisyChainPin);

// timer variables
unsigned long TimeNeeded;
unsigned long LastTimeUpdate = millis();

//
// Functions
//

void WaveWithLeftArm()
{
  // up
  LeftArmDaisyChain.setServoPosition(0, 200);
  LeftArmDaisyChain.communicate();
  
  // let motors calibrate
  TimeNeeded = 500;

  if (Time() == 1)
  {
    // down
    LeftArmDaisyChain.setServoPosition(0, 127);
    LeftArmDaisyChain.communicate();
  }
  
  if (Time() == 1)
  {
    // up again
    LeftArmDaisyChain.setServoPosition(0, 200);
    LeftArmDaisyChain.communicate();
  }

  if (Time() == 1)
  {
    // down all the way
    LeftArmDaisyChain.setServoPosition(0, 0);
    LeftArmDaisyChain.communicate();
  }
}

void WaveWithRightArm()
{
  // up
  RightArmDaisyChain.setServoPosition(0, 55);
  RightArmDaisyChain.communicate();
  
  // let motors calibrate
  TimeNeeded = 500;
  
  if (Time() == 1)
  {
    // down
    RightArmDaisyChain.setServoPosition(0, 127);
    RightArmDaisyChain.communicate();
  }
  
  if (Time() == 1)
  {
    // up again
    RightArmDaisyChain.setServoPosition(0, 55);
    RightArmDaisyChain.communicate();
  }
  
  if (Time() == 1)
  {
    // down all the way
    RightArmDaisyChain.setServoPosition(0, 255);
    RightArmDaisyChain.communicate();
  }
}

void RaiseLeftHand()
{
  LeftArmDaisyChain.setServoPosition(0, 200);
  LeftArmDaisyChain.communicate();
}

void RaiseRightHand()
{
  RightArmDaisyChain.setServoPosition(0, 55);
  RightArmDaisyChain.communicate();
}

void PutDownLeftHand()
{
  LeftArmDaisyChain.setServoPosition(0, 0);
  LeftArmDaisyChain.communicate();
}

void PutDownRightHand()
{
  RightArmDaisyChain.setServoPosition(0, 255);
  RightArmDaisyChain.communicate();
}

void TurnLeft()
{
  analogWrite(RightFootDCMotorPin, 255);
  TimeNeeded = 3000;

  if (Time() == 1)
  {
    // continue...
  }
}

void TurnRight()
{
  analogWrite(LeftFootDCMotorPin, 255);
  TimeNeeded = 3000;

  if (Time() == 1)
  {
    // continue...
  }
}

void MoveForward()
{
  analogWrite(LeftFootDCMotorPin, 255);
  analogWrite(RightFootDCMotorPin, 255);
  TimeNeeded = 3000;

  if (Time() == 1)
  {
    // continue...
  }
}

// bends at elbow with hand in front of robot
void ReceiveWithLeftHand()
{
  LeftArmDaisyChain.setServoPosition(1, 255);
  LeftArmDaisyChain.communicate();
}

// bends at elbow with hand in front of robot
void ReceiveWithRightHand()
{
  RightArmDaisyChain.setServoPosition(1, 0);
  RightArmDaisyChain.communicate();
}

// time without delay()
int Time()
{
  unsigned long Interval = TimeNeeded;
  unsigned long CurrentTime = millis();
  
  if ((CurrentTime - LastTimeUpdate) > Interval)
  {
    LastTimeUpdate = CurrentTime;
    
    // time is up
    return 1;
  }
  else
  {
    // time is not yet up
    return 0;
  }
}

void setup()
{
  // set up DC motors
  pinMode(LeftFootDCMotorPin, OUTPUT);
  pinMode(RightFootDCMotorPin, OUTPUT);
}

void loop()
{
  RaiseLeftHand();
  RaiseRightHand();
  TimeNeeded = 2000;

  if (Time() == 1)
  {
    // time is up; continue
    PutDownLeftHand();
    PutDownRightHand();
  }
  
  if (Time() == 1)
  {
    WaveWithLeftArm();
  }
  
  if (Time() == 1)
  {
    WaveWithRightArm();
  }
  
  if (Time() == 1)
  {
    TurnLeft();
    TimeNeeded = 1000;
  }
  
  if (Time() == 1)
  {
    TurnRight();
  }
  
  if (Time() == 1)
  {
    TimeNeeded = 2000;
    MoveForward();
  }
  
  if (Time() == 1)
  {
    ReceiveWithLeftHand();
  }
  
  if (Time() == 1)
  {
    PutDownLeftHand();
  }
  
  if (Time() == 1)
  {
    ReceiveWithRightHand();
  }
  
  if (Time() == 1)
  {
    PutDownRightHand();
  }
  
  if (Time() == 1)
  {
    // continue...
  }
}

I would suggest to visit less marketing and more technical and programming lectures.

Very funny. I have attended none of either. I taught myself everything I know about Arduino and programming.

For those of you who are entangled in this interminable thread, I present two data points.

Pete

That was an interesting "Rube Goldberg" experiment, although I think it does have a use. I just designed it wrong and put in the wrong features. On top of that, I did not understand the AVR architecture well enough. But what does that old failed project have to do with this?

goodinventor:
But what does that old failed project have to do with this?

See Reply #32

...R

I saw and read it, but I do not understand. My projects were never meant to be some sort of commercial cough project. Rather, I posted them because I thought they were incomplete and you all (who know more than I do) could help me. I am not in it for fame or money. I am doing this purely for my own amusement although I also want to share my projects. Do you understand better now?

Seems OP took Robin2 at his word in January 2015 when he said...

Take a year off

... and here we are.

During that time I've been doing research and improving my programming skills, though I really could use tons of improvement still.

improving my programming skills

Forget you ever heard of "goto", please.

@goodinventor, your youth and enthusiasm are wonderful.

The gap between your apparent abilities and what you aspire to is too wide for useful assistance on this Forum. To use my earlier analogy, you are like a 2nd week musician trying to participate in a guitar master class at the standard of Jimi Hendrix. You have not yet acquired either the technical skills or the background knowledge.

What concerns me is that by struggling unsuccessfully with something that is now far out of your reach you will miss the opportunity for the step-by-step acquisition of the skills that would allow you to contribute to Artificial Intelligence Research in the future.

...R

goodinventor:
Is this better?

//

// Deep Think 0.0.0.2
//
// programmed by George Andrews
//
// NOTE: This program is designed for the Meccanoid G15 (combined
// with the 86Duino One). It is a part of the Deep Think Project
// (first version of the software for the project). The Deep Think
// Project is designed to advance the intelligence (as well as
// motion and structural capabilities) of humanoid robots. This
// version of the program is designed to do the following.
//
// 1. Perform various moves using functions.
// 2. Control the 2 D/C motors with the 86Duino.
//
// Please note that this version is only intended as a demo to
// establish a basic framework for interfacing the Meccanoid
// electronic parts with the 86Duino One for future development.
// This version of the software, however, has the following
// additional capabilities compared to the previous version Deep
// Think 0.0.0.1.
//
// 1. Can interface with the D/C motors as well as the servos and
//    LED eyes.
// 2. Can perform various moves using functions in the program.
//

#include "MeccaBrain.h"

//
// Variables
//

// pin declarations
int LeftArmDaisyChainPin = 21;
int LEDEyePin = 29;
int RightArmDaisyChainPin = 38;
int LeftFootDCMotorPin = 11;
int RightFootDCMotorPin = 13;

// class objects
MeccaBrain LeftArmDaisyChain(LeftArmDaisyChainPin);
MeccaBrain LEDEye(LEDEyePin);
MeccaBrain RightArmDaisyChain(RightArmDaisyChainPin);

// timer variables
unsigned long TimeNeeded;
unsigned long LastTimeUpdate = millis();

//
// Functions
//

void WaveWithLeftArm()
{
  // up
  LeftArmDaisyChain.setServoPosition(0, 200);
  LeftArmDaisyChain.communicate();
 
  // let motors calibrate
  TimeNeeded = 500;

if (Time() == 1)
  {
    // down
    LeftArmDaisyChain.setServoPosition(0, 127);
    LeftArmDaisyChain.communicate();
  }
 
  if (Time() == 1)
  {
    // up again
    LeftArmDaisyChain.setServoPosition(0, 200);
    LeftArmDaisyChain.communicate();
  }

if (Time() == 1)
  {
    // down all the way
    LeftArmDaisyChain.setServoPosition(0, 0);
    LeftArmDaisyChain.communicate();
  }
}

void WaveWithRightArm()
{
  // up
  RightArmDaisyChain.setServoPosition(0, 55);
  RightArmDaisyChain.communicate();
 
  // let motors calibrate
  TimeNeeded = 500;
 
  if (Time() == 1)
  {
    // down
    RightArmDaisyChain.setServoPosition(0, 127);
    RightArmDaisyChain.communicate();
  }
 
  if (Time() == 1)
  {
    // up again
    RightArmDaisyChain.setServoPosition(0, 55);
    RightArmDaisyChain.communicate();
  }
 
  if (Time() == 1)
  {
    // down all the way
    RightArmDaisyChain.setServoPosition(0, 255);
    RightArmDaisyChain.communicate();
  }
}

void RaiseLeftHand()
{
  LeftArmDaisyChain.setServoPosition(0, 200);
  LeftArmDaisyChain.communicate();
}

void RaiseRightHand()
{
  RightArmDaisyChain.setServoPosition(0, 55);
  RightArmDaisyChain.communicate();
}

void PutDownLeftHand()
{
  LeftArmDaisyChain.setServoPosition(0, 0);
  LeftArmDaisyChain.communicate();
}

void PutDownRightHand()
{
  RightArmDaisyChain.setServoPosition(0, 255);
  RightArmDaisyChain.communicate();
}

void TurnLeft()
{
  analogWrite(RightFootDCMotorPin, 255);
  TimeNeeded = 3000;

if (Time() == 1)
  {
    // continue...
  }
}

void TurnRight()
{
  analogWrite(LeftFootDCMotorPin, 255);
  TimeNeeded = 3000;

if (Time() == 1)
  {
    // continue...
  }
}

void MoveForward()
{
  analogWrite(LeftFootDCMotorPin, 255);
  analogWrite(RightFootDCMotorPin, 255);
  TimeNeeded = 3000;

if (Time() == 1)
  {
    // continue...
  }
}

// bends at elbow with hand in front of robot
void ReceiveWithLeftHand()
{
  LeftArmDaisyChain.setServoPosition(1, 255);
  LeftArmDaisyChain.communicate();
}

// bends at elbow with hand in front of robot
void ReceiveWithRightHand()
{
  RightArmDaisyChain.setServoPosition(1, 0);
  RightArmDaisyChain.communicate();
}

// time without delay()
int Time()
{
  unsigned long Interval = TimeNeeded;
  unsigned long CurrentTime = millis();
 
  if ((CurrentTime - LastTimeUpdate) > Interval)
  {
    LastTimeUpdate = CurrentTime;
   
    // time is up
    return 1;
  }
  else
  {
    // time is not yet up
    return 0;
  }
}

void setup()
{
  // set up DC motors
  pinMode(LeftFootDCMotorPin, OUTPUT);
  pinMode(RightFootDCMotorPin, OUTPUT);
}

void loop()
{
  RaiseLeftHand();
  RaiseRightHand();
  TimeNeeded = 2000;

if (Time() == 1)
  {
    // time is up; continue
    PutDownLeftHand();
    PutDownRightHand();
  }
 
  if (Time() == 1)
  {
    WaveWithLeftArm();
  }
 
  if (Time() == 1)
  {
    WaveWithRightArm();
  }
 
  if (Time() == 1)
  {
    TurnLeft();
    TimeNeeded = 1000;
  }
 
  if (Time() == 1)
  {
    TurnRight();
  }
 
  if (Time() == 1)
  {
    TimeNeeded = 2000;
    MoveForward();
  }
 
  if (Time() == 1)
  {
    ReceiveWithLeftHand();
  }
 
  if (Time() == 1)
  {
    PutDownLeftHand();
  }
 
  if (Time() == 1)
  {
    ReceiveWithRightHand();
  }
 
  if (Time() == 1)
  {
    PutDownRightHand();
  }
 
  if (Time() == 1)
  {
    // continue...
  }
}

I don't think that code will do what you seem to think it will do.

It certainly won't act like the code with the delays would. Ohhhhh no!

You did NOT learn the BWOD lesson but you do seem to have grasped the know-how-long-it's-been part of it. Spend some time on the implications, make 2 leds blink at different rates or 2 serial messages print at different rates, just to start.

Here's a simple challenge I propose to people who think they've fully grasped the BWOD Principle, and you can do it on a bare Arduino: make the LED on pin 13 fade up down, without using delay.
For bonus marks, add a potentiometer and vary the fade rate.

goodinventor:
Is this better? MorganS, the answer is that I intend to have other things going on, but not just yet. I am working on getting the servos to work right now, but it makes sense to go ahead and write a non-blocking version of delay() because in the near future I will add sensors to the code. I would like to implement multitasking in the near future.

//

// Deep Think 0.0.0.2
//
// programmed by George Andrews
//
// NOTE: This program is designed for the Meccanoid G15 (combined
// with the 86Duino One). It is a part of the Deep Think Project
// (first version of the software for the project). The Deep Think
// Project is designed to advance the intelligence (as well as
// motion and structural capabilities) of humanoid robots. This
// version of the program is designed to do the following.
//
// 1. Perform various moves using functions.
// 2. Control the 2 D/C motors with the 86Duino.
//
// Please note that this version is only intended as a demo to
// establish a basic framework for interfacing the Meccanoid
// electronic parts with the 86Duino One for future development.
// This version of the software, however, has the following
// additional capabilities compared to the previous version Deep
// Think 0.0.0.1.
//
// 1. Can interface with the D/C motors as well as the servos and
//    LED eyes.
// 2. Can perform various moves using functions in the program.
//

#include "MeccaBrain.h"

//
// Variables
//

// pin declarations
int LeftArmDaisyChainPin = 21;
int LEDEyePin = 29;
int RightArmDaisyChainPin = 38;
int LeftFootDCMotorPin = 11;
int RightFootDCMotorPin = 13;

// class objects
MeccaBrain LeftArmDaisyChain(LeftArmDaisyChainPin);
MeccaBrain LEDEye(LEDEyePin);
MeccaBrain RightArmDaisyChain(RightArmDaisyChainPin);

// timer variables
unsigned long TimeNeeded;
unsigned long LastTimeUpdate = millis();

//
// Functions
//

void WaveWithLeftArm()
{
  // up
  LeftArmDaisyChain.setServoPosition(0, 200);
  LeftArmDaisyChain.communicate();
 
  // let motors calibrate
  TimeNeeded = 500;

if (Time() == 1)
  {
    // down
    LeftArmDaisyChain.setServoPosition(0, 127);
    LeftArmDaisyChain.communicate();
  }
 
  if (Time() == 1)
  {
    // up again
    LeftArmDaisyChain.setServoPosition(0, 200);
    LeftArmDaisyChain.communicate();
  }

if (Time() == 1)
  {
    // down all the way
    LeftArmDaisyChain.setServoPosition(0, 0);
    LeftArmDaisyChain.communicate();
  }
}

void WaveWithRightArm()
{
  // up
  RightArmDaisyChain.setServoPosition(0, 55);
  RightArmDaisyChain.communicate();
 
  // let motors calibrate
  TimeNeeded = 500;
 
  if (Time() == 1)
  {
    // down
    RightArmDaisyChain.setServoPosition(0, 127);
    RightArmDaisyChain.communicate();
  }
 
  if (Time() == 1)
  {
    // up again
    RightArmDaisyChain.setServoPosition(0, 55);
    RightArmDaisyChain.communicate();
  }
 
  if (Time() == 1)
  {
    // down all the way
    RightArmDaisyChain.setServoPosition(0, 255);
    RightArmDaisyChain.communicate();
  }
}

void RaiseLeftHand()
{
  LeftArmDaisyChain.setServoPosition(0, 200);
  LeftArmDaisyChain.communicate();
}

void RaiseRightHand()
{
  RightArmDaisyChain.setServoPosition(0, 55);
  RightArmDaisyChain.communicate();
}

void PutDownLeftHand()
{
  LeftArmDaisyChain.setServoPosition(0, 0);
  LeftArmDaisyChain.communicate();
}

void PutDownRightHand()
{
  RightArmDaisyChain.setServoPosition(0, 255);
  RightArmDaisyChain.communicate();
}

void TurnLeft()
{
  analogWrite(RightFootDCMotorPin, 255);
  TimeNeeded = 3000;

if (Time() == 1)
  {
    // continue...
  }
}

void TurnRight()
{
  analogWrite(LeftFootDCMotorPin, 255);
  TimeNeeded = 3000;

if (Time() == 1)
  {
    // continue...
  }
}

void MoveForward()
{
  analogWrite(LeftFootDCMotorPin, 255);
  analogWrite(RightFootDCMotorPin, 255);
  TimeNeeded = 3000;

if (Time() == 1)
  {
    // continue...
  }
}

// bends at elbow with hand in front of robot
void ReceiveWithLeftHand()
{
  LeftArmDaisyChain.setServoPosition(1, 255);
  LeftArmDaisyChain.communicate();
}

// bends at elbow with hand in front of robot
void ReceiveWithRightHand()
{
  RightArmDaisyChain.setServoPosition(1, 0);
  RightArmDaisyChain.communicate();
}

// time without delay()
int Time()
{
  unsigned long Interval = TimeNeeded;
  unsigned long CurrentTime = millis();
 
  if ((CurrentTime - LastTimeUpdate) > Interval)
  {
    LastTimeUpdate = CurrentTime;
   
    // time is up
    return 1;
  }
  else
  {
    // time is not yet up
    return 0;
  }
}

void setup()
{
  // set up DC motors
  pinMode(LeftFootDCMotorPin, OUTPUT);
  pinMode(RightFootDCMotorPin, OUTPUT);
}

void loop()
{
  RaiseLeftHand();
  RaiseRightHand();
  TimeNeeded = 2000;

if (Time() == 1)
  {
    // time is up; continue
    PutDownLeftHand();
    PutDownRightHand();
  }
 
  if (Time() == 1)
  {
    WaveWithLeftArm();
  }
 
  if (Time() == 1)
  {
    WaveWithRightArm();
  }
 
  if (Time() == 1)
  {
    TurnLeft();
    TimeNeeded = 1000;
  }
 
  if (Time() == 1)
  {
    TurnRight();
  }
 
  if (Time() == 1)
  {
    TimeNeeded = 2000;
    MoveForward();
  }
 
  if (Time() == 1)
  {
    ReceiveWithLeftHand();
  }
 
  if (Time() == 1)
  {
    PutDownLeftHand();
  }
 
  if (Time() == 1)
  {
    ReceiveWithRightHand();
  }
 
  if (Time() == 1)
  {
    PutDownRightHand();
  }
 
  if (Time() == 1)
  {
    // continue...
  }
}

So, let me understand this, the Time() function returns true if it is more than TimeNeeded milliseconds since the last time it returned true? What if you haven't used it in a while? You can't get a negative delay.

Try and take on AWOL's challenge. It's a little fuzzy on the details so you may need to ask him for clarification but I have a solution in mind that will be only 20 lines of code.

MorganS:
What if you haven't used it in a while?

The way the loop is written, that isn't likely to happen - there are much bigger issues with the current structure.

As it is, loop() will get called frequently. In each pass, the robot will start to raise both arms, then it will start checking whether the time has expired. Most of the time this will be false, and all of the if statements will skip their processing, and the loop will quickly exit and start over (by immediately starting to raise arms again.) finally, the time will expire, but it's impossible to predict which if statement will return first - it's pure random chance where the code will be at when millis() finally returns the target time.

The net result is that on each loop the robot will start to raise it's arms, and then every two seconds it will randomly do some other operation, but then immediately go back to the top of the loop and raise the arms again. I predict the externally visible result will be a robot that raises both arms, and then every two seconds makes a brief buzz or click as it starts to do something else and then immediately goes back to raising the arms. Or at least that's what the arm servos will do - if it happens to hit a command that tries to lower them, it will once again raise them so quickly they might not even have time to move. I don't know enough about the robot's details to know if other motors will do anything - they may do nothing, or may operate erratically or randomly.

I said that which function will trigger is completely random: that's not quite true. The odds are somewhat in favor of the first if statement, the one that puts down the arms. That's because the window of opportunity for the time to change between each if statement is small, since they are one after each other. However, after the last if statement, there is the time it takes to return from the function, loop around, re-enter the function, call the raise arms functions, and set TimeNeeded. This will all be fast, but will still take more time than evaluating each if condition - since it spends more time before this if condition than the others, there is a rather chance that millis() will hit the target time then, so the window of opportunity is larger for that first if. So the odds are higher that it will be that one that periodically triggers.

Having a bunch of delay() calls in a program like this is generally a bad idea. But using this method of timing is FAR worse!

The issue is not that delay() is inherently evil - the real problem is writing a loop() function that does a long process step by step and doesn't return until the whole sequence is done. That's what causes problems - delay() is just an easy way to make such a long blocking sequence: it's a symptom, not the disease. By re-writing delay into a Time() function, you are not solving the root problem.

Goodinventor: this is a good learning opportunity, and you should take some time to research "finite state machines" - that will be a necessary component to getting this to work properly, much more valuable than simply rewriting delay() or using multiple processors.

Robin2: Perhaps I have not made myself clear on what I am currently trying to do. I am not trying to do something out of my reach. At the moment the hardware is just a little beyond my current knowledge. I need to learn a little more about finite state machines to control my robot in a simple, predictable way, I need to learn how to control servos (which I recently did), and I need to learn about a few of the basic I/O protocols (SPI, UART, I2C, and CAN). The robot at the moment is only a little more complex than a basic wheeled robot.

I am not trying to do something out of my reach.

Then why did you choose the rather bold title of this thread to be "Artificial Intelligence Research Project"?

Many very smart people having been working on similarly titled projects, in large groups, for several decades now, with computers many orders of magnitude more powerful than an Arduino.

And despite Steven Hawking's dire predictions, artificial intelligence doesn't seem to be a gleam in anyone's eye, let alone a pressing threat.

ShapeShifter: All right, so basically my logic within loop() is all wrong. Are there any issues in the Time() function itself. I looked hard at the code for BWoD, but I cannot see a clear way to fix my code.