Autonomous Robot Part 3 – TicTok

Group Member: Horace Hou, Zac Mau

Horace Hou, Zac Mau as Scribe, Designer, Integrator, Tutor,

 

Introduction

For this iteration we tried to incorporate ideas of one to many mapping into our project as way to make the interaction of the clock hands and the elastic to be more clear.

 

Technical Notes

The hardware of the project hasn’t changed much whereas the software changed a lot. Hardware wise we flipped the side of the clock hand the elastic was on so as to minimise it from getting tangled. Software wise we tried to incorporate an PureData sketch with an Arduino code.

Circuit Diagram

Clock schematic

Photos

tictok4

tictok2 copy tictok1 tictok3 copy

Arduino Code

#include <Servo.h>
#include <Stepper.h>
#define MAX_SPEED 1000
const int stepsPerRevolution = 200;
int speed1 = 200;
int speed2 = 200;
int sensorNow;
int sensorLast;
// for your motor
// initialize the stepper library on pins 8 through 11:
Stepper stepper1(stepsPerRevolution, 6, 7);
Stepper stepper2(stepsPerRevolution, 8, 9);
static unsigned int hardware_polling_interval = 50; // 20 Hz samples to start
// The maximum message line length.
#define MAX_LINE_LENGTH 80
// The maximum number of tokens in a single message.
#define MAX_TOKENS 10
// Some version of the Arduino IDE don’t correctly define this symbol for an
// Arduino Uno.
/****************************************************************/
/**** Utility functions *****************************************/
/****************************************************************/
// Send a single debugging string to the console.
static void send_debug_message( const char *str )
{
  Serial.print(“dbg “);
  Serial.println( str );
}
/****************************************************************/
// Send a single debugging integer to the console.
static void send_debug_message( int i )
{
  Serial.print(“dbg “);
  Serial.println( i );
}
/****************************************************************/
// Send a single-argument message back to the host.
static void send_message( const char *command, long value )
{
  Serial.print( command );
  Serial.print( ” ” );
  Serial.println( value );
}
/****************************************************************/
// Send a two-argument message back to the host.
static void send_message( const char *command, long value1, long value2 )
{
  Serial.print( command );
  Serial.print( ” ” );
  Serial.print( value1 );
  Serial.print( ” ” );
  Serial.println( value2 );
}
/****************************************************************/
// Wrapper on strcmp for clarity of code.  Returns true if strings are
// identical.
static int string_equal( char *str1, char *str2)
{
  return !strcmp(str1, str2);
}
static void user_message_0( char *command )
{
  if (string_equal(command, “stop”)) {
    // do something to set the stop state here
    send_debug_message(“now stopped”);
  } else  if (string_equal(command, “start”)) {
    // do something to set the start state here
    send_debug_message(“starting”);
  }
  // …
}
// Process one-argument messages with a single value. E.g. “speed 33”.
static void user_message_1( char *command, int value )
{
  if (string_equal(command, “speed”)) {
    // do something to set the stop state using ‘value’
  }
  // …
}
// Process two-argument messages. E.g. “pantilt 0 33”.
static void user_message_2( char *command, int value1, int value2 )
{
  if (string_equal(command, “pantilt”)) {
    // do something using value1 and value2
  }
  // …
}
/****************************************************************/
// Process an input message.  Unrecognized commands are silently ignored.
static void parse_input_message(int argc, char *argv[])
{
  // Interpret the first token as a command symbol.
  char *command = argv[0];
  /* — process zero-argument commands ————————— */
  if (argc == 1) {
    send_message(“dbg”, 0, 1);
    // just pass it along
    user_message_0( command );
  }
  /* — process two-argument commands ————————— */
  else if (argc == 3) {
    send_message(“dbg”, 0, 2);
    int pin   = atoi(argv[1] );
    int value = atoi(argv[2] );
    if ( string_equal( command, “stepper” )) {
      if(pin == 0)  {
        stepper1.setSpeed(value);
        send_message(“dbg”, 0, value);
      }
      else if(pin == 1)  {
        stepper2.setSpeed(value);
        send_message(“dbg”, 1, value);
      }
      return;
    }
    else if ( string_equal( command, “dig” )) {
      pinMode( pin, OUTPUT );
      digitalWrite( pin, value );
      return;
    }
    // else just pass it along
    else user_message_2( command, pin, value );
  }
}
/****************************************************************/
// Polling function to process messages arriving over the serial port.  Each
// iteration through this polling function processes at most one character.  It
// records the input message line into a buffer while simultaneously dividing it
// into ‘tokens’ delimited by whitespace.  Each token is a string of
// non-whitespace characters, and might represent either a symbol or an integer.
// Once a message is complete, parse_input_message() is called.
static void serial_input_poll(void)
{
  static char input_buffer[ MAX_LINE_LENGTH ];   // buffer for input characters
  static char *argv[MAX_TOKENS];                 // buffer for pointers to tokens
  static int chars_in_buffer = 0;  // counter for characters in buffer
  static int chars_in_token = 0;   // counter for characters in current partially-received token (the ‘open’ token)
  static int argc = 0;             // counter for tokens in argv
  static int error = 0;            // flag for any error condition in the current message
  // Check if at least one byte is available on the serial input.
  if (Serial.available()) {
    int input = Serial.read();
    // If the input is a whitespace character, end any currently open token.
    if ( isspace(input) ) {
      if ( !error && chars_in_token > 0) {
if (chars_in_buffer == MAX_LINE_LENGTH) error = 1;
else {
  input_buffer[chars_in_buffer++] = 0;  // end the current token
  argc++;                               // increase the argument count
  chars_in_token = 0;                   // reset the token state
}
      }
      // If the whitespace input is an end-of-line character, then pass the message buffer along for interpretation.
      if (input == ‘\r’ || input == ‘\n’) {
// if the message included too many tokens or too many characters, report an error
if (error) send_debug_message(“excessive input error”);
// else process any complete message
else if (argc > 0) parse_input_message( argc, argv );
// reset the full input state
error = chars_in_token = chars_in_buffer = argc = 0;
      }
    }
    // Else the input is a character to store in the buffer at the end of the current token.
    else {
      // if beginning a new token
      if (chars_in_token == 0) {
// if the token array is full, set an error state
if (argc == MAX_TOKENS) error = 1;
// otherwise save a pointer to the start of the token
else argv[ argc ] = &input_buffer[chars_in_buffer];
      }
      // the save the input and update the counters
      if (!error) {
if (chars_in_buffer == MAX_LINE_LENGTH) error = 1;
else {
  input_buffer[chars_in_buffer++] = input;
  chars_in_token++;
}
      }
    }
  }
}
static void hardware_input_poll(void)
{
  static unsigned long last_time = 0;
  unsigned long now = millis();
  if ((now – last_time) > hardware_polling_interval) {
    last_time = now;
    // send A0 analog state
    send_message( “ana”, 0, analogRead(0) );
    // send PIN8 digital state
    send_message( “dig”, 7, digitalRead(7) );
    send_message( “dig”, 9, digitalRead(9) );
    // send a time reading
    long clock = micros();
    send_message( “clk”, clock );
  }
}
void setup()
{
  Serial.begin(9600);// nothing to do inside the setup
  // initialize the Serial port
  // send a message as a diagnostic
  send_debug_message(“wakeup”);
  // set up the hobby servo control output
  //servo_output.attach( servo_output_pin );
  //servo_output.attach( servo_output_pin_2 );
  // additional hardware configuration can go here
}
void loop()
{
  serial_input_poll();
  hardware_input_poll();
}