Sara Johnson – Physical Computing https://courses.ideate.cmu.edu/16-223/f2014 Carnegie Mellon University, IDeATe Fri, 11 Aug 2017 21:41:33 +0000 en-US hourly 1 https://wordpress.org/?v=4.7.28 Autonomous Robot Part 3 – Marco Robo https://courses.ideate.cmu.edu/16-223/f2014/autonomous-robot-3-marco-robo/ Tue, 18 Nov 2014 20:56:09 +0000 http://courses.ideate.cmu.edu/physcomp/f14/16-223/?p=2888 Marco Robo

Team members: Ruben Markowitz, Bryan Gardiner, Sara Johnson

Roles: Bryan Gardiner(Integrator and Scribe), Sara Johnson(Integrator and Designer), Ruben Markowitz(Designer and Tutor)

Introduction

Marco Robo is a robot that explores its surroundings and creates a visual and physical map that shows how the robot perceives the outside world. In the third iteration of the project, we redesigned the device to rotate around a fixed axis so Marco Robo interprets the change in a room over time.

Marco Robo rolls around a center pivot, and uses a sonar sensor to measure the distance of objects in front of it. If the robot sees nothing in its range, it will rotate on the outer ring of its motion. When objects move into its field of view, it will mark what it sees by driving inward toward its axis and making a divot in its path. Overtime, the robot creates a circular map of the location and frequency of disturbances.

Video

Technical Specs

The movement of Marco Robo is driven by a geared motor, controlling its angular position, and a stepper motor, controlling its radial location. The robot moves on two omni wheels that allow free radial and axial movement, and one fixed wheel that drives it radially. Marco Robo uses a sonar sensor to collect and average the distance of objects immediately in front of it, and then scales the object size to the length of the gear arm. The drive box then moves this distance as it turns, moving the marker fixed to the drive box, and creates a map over time.

IMG_5054frontdrawing

 

IMG_5064wheels

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Circuit Schematic

 schematic

Code

//Marco Robo
//Ruben Markowitz, Bryan Gardiner, Sara Johnson

//*************************IMPORTS**************************************************//

#include <Wire.h>
#include <NewPing.h>
#include <AccelStepper.h>
//*************************GLOBAL DEFINITIONS***************************************//

//Digital Pin Definitions
int rMotorDirectionPin = 2;
int rMotorStepPin = 3;
int thetaMotorDirectionPin1 = 4;
int thetaMotorDirectionPin2 = 5;
int innerHomeSensorLightPin = 6;
int outerHomeSensorLightPin = 7;
int rangeEcho = 8;
int rangeTrig = 9;
int rangeMax = 200;

//Analog Pin Definitions
int innerHomeSensorPin = 0;
int outerHomeSensorPin = 1;
int gyroPin = 2;

//DirectionModifiers
boolean rMotorDirectionSet = false;
boolean thetaMotorDirectionSet = true;

//Threshold Modifiers
int innerHomeSensorLow = 700;
int outerHomeSensorLow = 200;
int sonarSamples = 20;
float driveGearCircum = 1.67894;
int driveWheelCircum = 54;
int stepperStepsPerRev = 200;
int robotLen = 15.1;

//Dynamics
float currentTheta = 0;
float currentDistance = 0;
float currentR = 0;
float nextR = 10;
float travelLength = 0;
float currentCircum = 0;
float rangeToRFactor = 0;

//Class Instances
NewPing range(rangeTrig, rangeEcho, rangeMax);

//****************************DRIVE CODE***************************************//
void driveR(String dir){
if(rMotorDirectionSet){
if(dir == “forward”){
digitalWrite(rMotorDirectionPin, HIGH);
}
else if(dir == “backward”){
digitalWrite(rMotorDirectionPin, LOW);
}
}
else{
if(dir == “forward”){
digitalWrite(rMotorDirectionPin, LOW);
}
else if(dir == “backward”){
digitalWrite(rMotorDirectionPin, HIGH);
}
}
//Serial.print(“Stepping “);
//Serial.println(dir);
digitalWrite(rMotorStepPin, HIGH);
delay(1);
digitalWrite(rMotorStepPin, LOW);
delay(1);
}

void driveTheta(String dir){
if(thetaMotorDirectionSet){
if(dir == “forward”){
digitalWrite(thetaMotorDirectionPin1, HIGH);
digitalWrite(thetaMotorDirectionPin2, LOW);
}
else if(dir == “backward”){
digitalWrite(thetaMotorDirectionPin1, LOW);
digitalWrite(thetaMotorDirectionPin2, HIGH);
}
}
else{
if(dir == “forward”){
digitalWrite(thetaMotorDirectionPin1, LOW);
digitalWrite(thetaMotorDirectionPin2, HIGH);
}
else if(dir == “backward”){
digitalWrite(thetaMotorDirectionPin1, HIGH);
digitalWrite(thetaMotorDirectionPin2, LOW);
}
}
//Serial.print(“Stepping “);
//Serial.println(dir);

delay(1);
}
//**************************RANGE CODE********************************************//
void detectRange(){
//Serial.println(“Gathering Sonar Data…”);
int pingData = 0;
for(int i = 0; i < sonarSamples; i ++){
pingData = (range.ping() / US_ROUNDTRIP_CM);
//Serial.print(“Ping Data: “);
//Serial.println(pingData);
currentDistance += pingData;
}
currentDistance /= sonarSamples;
if(currentDistance>=50) currentDistance=55;
//Serial.print(“Current Distance is: “);
//Serial.println(currentDistance);
}

//********************CALIBRATE CODE*********************************************//
void calibrateR(){
/*
//Serial.println(“Calibrating R”);
digitalWrite(innerHomeSensorLightPin, HIGH);
//Serial.println(“Inner Sensor Light is On”);
int homeSensorVal = analogRead(innerHomeSensorPin);
innerHomeSensorLow=homeSensorVal;
//Serial.print(“Current Light Sensor Value is: “);
//Serial.println(homeSensorVal);
while((homeSensorVal-innerHomeSensorLow)<25 and (innerHomeSensorLow-homeSensorVal)<25){
driveR(“backward”);
homeSensorVal = analogRead(innerHomeSensorPin);
//Serial.print(“Current Light Sensor Value is: “);
//Serial.println(homeSensorVal);
}
//Serial.println(“Switching Direction”);
digitalWrite(innerHomeSensorLightPin, LOW);
digitalWrite(outerHomeSensorLightPin, HIGH);
delay(500);
homeSensorVal = analogRead(outerHomeSensorPin);
//Serial.print(“Current Light Sensor Value is: “);
//Serial.println(homeSensorVal);
while(homeSensorVal >= outerHomeSensorLow){
driveR(“forward”);
travelLength += 1;
homeSensorVal = analogRead(innerHomeSensorPin);
//Serial.print(“Current Light Sensor Value is: “);
//Serial.println(homeSensorVal);
}
digitalWrite(outerHomeSensorLightPin, LOW);
travelLength = travelLength / 200;
travelLength = travelLength / driveGearCircum;
//Serial.print(“Travel Length is: “);
//Serial.print(travelLength);
//Serial.println(” cm”);
currentR = travelLength;
//Serial.println(“Finished Calibrating R”);
*/
currentR=10;
travelLength=50;
}

void calibrateRange(){
//Serial.println(“Calibrating Sonar Sensor LOL”);
float rangeOffsetMean;
int pingData = 0;
for(int i = 0; i < sonarSamples; i ++){
pingData = (range.ping() / US_ROUNDTRIP_CM);
//Serial.print(“Ping Data: “);
//Serial.println(pingData);
rangeOffsetMean += pingData;
}
rangeOffsetMean /= sonarSamples;
//Serial.print(“Average reading of: “);
//Serial.println(rangeOffsetMean);

}
//*****************************MATH FUNCTIONS**********************************//
void rangeToR(){
rangeToRFactor = (travelLength / rangeMax);
nextR = currentDistance * rangeToRFactor;
}
//*****************************MAIN CODE***************************************//

void setup(){
//Pin Setup
pinMode(rMotorDirectionPin, OUTPUT);
digitalWrite(rMotorDirectionPin, LOW);
pinMode(rMotorStepPin, OUTPUT);
digitalWrite(rMotorStepPin, LOW);
pinMode(thetaMotorDirectionPin1, OUTPUT);
digitalWrite(thetaMotorDirectionPin1, LOW);
pinMode(thetaMotorDirectionPin2, OUTPUT);
digitalWrite(thetaMotorDirectionPin2, LOW);
pinMode(innerHomeSensorLightPin, OUTPUT);
digitalWrite(innerHomeSensorLightPin, LOW);
pinMode(outerHomeSensorLightPin, OUTPUT);
digitalWrite(outerHomeSensorLightPin, LOW);
pinMode(rangeEcho, INPUT);
pinMode(rangeTrig, OUTPUT);
digitalWrite(rangeTrig, LOW);

//Start Serial
Serial.begin(9600);
Wire.begin();

//Run Calibration Sequence
//Serial.println(“Calibrating R”);
calibrateR();
//Serial.println(“Now Calibrating Theta”);
calibrateRange();
//Serial.println(“Finished Calibrating!”);
//Serial.println(“”);
//Serial.println(“”);
//Serial.println(“”);
//Serial.println(“”);
//Serial.println(“Begin Behavior”);
}

void loop(){
//Serial.print(“Current Position: R = “);
//Serial.print(currentR);
//Serial.print(“, Theta = “);
//Serial.println(currentTheta);
//Serial.print(“Detecting range…”);
detectRange();
rangeToR();
//Serial.print(“Moving R to “);
//Serial.println(nextR);
if(currentR – nextR < 0){
while(currentR < nextR){
driveR(“forward”);
currentR = currentR +(driveGearCircum/stepperStepsPerRev);
//Serial.print(“Current Position: R = “);
//Serial.print(currentR);
}
}
else if(currentR – nextR > 0){
while(currentR > nextR){
driveR(“backward”);
currentR = currentR – (driveGearCircum/stepperStepsPerRev);
//Serial.print(“Current Position: R = “);
//Serial.print(currentR);
}
}
//Serial.println(“Moving to next Theta”);
currentCircum = (currentR + robotLen) * 2 * 3.14;
for(int steps = 0; steps <= ((currentCircum/360)/driveWheelCircum)*200; steps ++){
driveTheta(“forward”);
}
currentTheta += 1;
delay(100);
}

Project Progression

Iteration 1 - gantry arm

Iteration 1 – gantry arm, threaded rod, rectangular base, 4 wheels

Iteration 2 – gantry arm, timing belt, semicircular base, 3 wheels

]]>
Autonomous Robot Part 2 – Marco Robo https://courses.ideate.cmu.edu/16-223/f2014/autonomous-robot-2b-marco-robo/ Tue, 04 Nov 2014 21:03:57 +0000 http://courses.ideate.cmu.edu/physcomp/f14/16-223/?p=2655 Marco Robo

Team members: Ruben Markowitz, Bryan Gardiner, Sara Johnson

Introduction

We are creating an automous robot that explores its surroundings, and maps its journey in attempt to understand its place in the world. Marco Robo travels until it encounters an obstacle, and turns to journey in new, unknown directions. It draws its progression on a map on its back during travel to retain what it has learned.

marco side

Technical Notes

Our robot travels on four wheels: two are driven by geared down motors and two are omni-wheels that allow movement in any direction. The drawing mechanism sweeps the pen radially with a stepper motor, and forward and back on a winch, also driven by a stepper motor. The motors are driven by two stepper motors, communicating with an arduino uno. The robot maintains its reference location with a compass, and the map-drawing is scaled to the size of the room.

Circuit Diagram

marco cir

Marco Robo internals.

Marco Robo internals.

marco base

Platform holding paper.

marco marker housing

Marker housing driven by winch.

 

Code

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_LSM303.h>

int step1 = 12;
int direct1 = 11;
int step2 = 10;
int direct2 = 9;
int leftMotorPlus=8;
int leftMotorMinus=7;
int rightMotorPlus=6;
int rightMotorMinus=5;

int posR=0;
int posTheta=0;
int movTheta=0;
int movR=0;
int zR=0;
int zTheta=0;
int zX=0;
int zY=0;
int temp1=0;
int temp2=0;
int drawing=0;
int turning=0;
int minDistance=2;
float heading2=0;
/* Assign a unique ID to this sensor at the same time */
Adafruit_LSM303_Mag mag = Adafruit_LSM303_Mag(12345);

void setup() {
pinMode(step1,OUTPUT);
pinMode(direct1,OUTPUT);
pinMode(step2,OUTPUT);
pinMode(direct2,OUTPUT);
pinMode(leftMotorPlus,OUTPUT);
pinMode(leftMotorMinus,OUTPUT);
pinMode(rightMotorPlus,OUTPUT);
pinMode(rightMotorMinus,OUTPUT);
pinMode(A2,OUTPUT);
pinMode(A3,OUTPUT);
sensors_event_t event;
mag.getEvent(&event);

float Pi = 3.14159;
heading2 = (atan2(event.magnetic.y,event.magnetic.x) * 180) / Pi;
if (heading2 < 0)
{
heading2 = 360 + heading;
heading2=heading2/360;
heading2=heading2*(2*pi);
}

}

void loop()
{
sensors_event_t event;
mag.getEvent(&event);

float Pi = 3.14159;
float movTheta = (atan2(event.magnetic.y,event.magnetic.x) * 180) / Pi;
if (movTheta < 0)
{
movTheta = 360 + movTheta;
movTheta=movTheta/360;
movTheta=movTheta*(2*pi);
movTheta=movTheta-heading2;
}

turning=0;
if(analogRead(A2)>minDistance or analogRead(A3)>minDistance)
{
turning=1;
}
if(drawing==1)
{
temp1=posR*cos(posTheta);
temp2=movR*cos(movTheta);
zX=temp1+temp2;
temp1=posR*sin(posTheta);
temp2=movR*sin(movTheta);
zY=temp1+temp2;

zR=sqrt(zX*zX+zY*zY);
zTheta=atan(zY/zX);

for(int i=0;i<abs(zR-posR);i++)
{
if((zR-posR)>=0)
{
digitalWrite(direct1,HIGH);
}
else
{
digitalWrite(direct1,LOW);
}
digitalWrite(step1,HIGH);
delay(1);
}
digitalWrite(step1,LOW);
for(int i=0;i<abs(zTheta-posTheta);i++)
{
if((zTheta-posTheta)>=0)
{
digitalWrite(direct2,HIGH);
}
else
{
digitalWrite(direct2,LOW);
}
digitalWrite(step2,HIGH);
delay(1);
}
digitalWrite(step2,LOW);

posR=zR;
posTheta=zTheta;
drawing=0;
movR=0;
}

if(turning==1 && drawing==0)
{
digitalWrite(leftMotorPlus,LOW);
digitalWrite(leftMotorMinus,HIGH);
digitalWrite(rightMotorPlus,LOW);
digitalWrite(rightMotorMinus,LOW);
digitalWrite(step1,LOW);
digitalWrite(step2,LOW);
delay(500);
movTheta+=1;

}

if(turning==0 && drawing==0)
{
digitalWrite(leftMotorPlus,HIGH);
digitalWrite(leftMotorMinus,LOW);
digitalWrite(rightMotorPlus,HIGH);
digitalWrite(rightMotorMinus,LOW);
digitalWrite(step1,LOW);
digitalWrite(step2,LOW);
delay(1000);
movR+=5;
drawing=1;
}
}

 

]]>
1B – Arduino Project – we-cig https://courses.ideate.cmu.edu/16-223/f2014/1b-arduino-project-we-cig/ Mon, 22 Sep 2014 04:20:50 +0000 http://courses.ideate.cmu.edu/physcomp/f14/16-223/?p=1894 Group Members: Sara Johnson, Miles Peyton, Akiva Krauthamer, Brian Yang

Roles: Miles Peyton as tutor, Brian Yang as Integrator, Akiva Krauthamer as designer, Sara Johnson as scribe

 

Introduction

While smoking is a social activity between two people physically together, we aim to make smoking connect long distance friends. Our we-cigs come in connected pairs. When a person inhales, their friend’s cigarette tip glows, and dims as a the person exhales. We aim to communicate the intimacy of a friend’s breathe – a life sustaining act – while smoking – a life killing act. The e-cigarettes connect two people through their action and vices.

 

Video

 

Technical Notes

Our we-cigs use two electronic cigarettes triggered by the airflow of an inhaling breathe. The e-cigarettes’ built-in LED glows during inhalation, and is sensed by an ambient light sensor. The light sensor then sends out a wireless pulse, that talks to the friend’s wireless device, turning on their we-cig’s light.

The we-cigs are programmed using the Teensy 3.1 arduino to reduce the size to fit comfortably in a hand. We used the Wixel Wireless Module to connect the Social Cigs using a 2.4 GHz radio.

The form of the cigarette is chosen to be large enough to contain the hardware, while being held comfortably in one hand. The imprint of your friend’s hand is molded externally on to your cigarette. So the form suggests how to hold the device, but when picking up your we-cig, it does not fit perfectly in your fingers. Feeling the imprint of your friend’s hand is a reminder of the long distance connection.

 

Photos

Social Cig - Circuit Diagram

we-cig Circuit Diagram

 

Social Cig Internals. The e-cigarette is sitting between the Teensy 3.1 on the left and the wixel on the right.

we-cig internals. The e-cigarette is sitting between the Teensy 3.1 on the left and the Wixel on the right.

 

Code

See code here.

]]>