From 0ff1d58c97eade06d0ccdd9dc9159b462b54bd05 Mon Sep 17 00:00:00 2001 From: JJROBOTS Date: Wed, 29 Mar 2017 17:38:40 +0100 Subject: [PATCH] B-ROBOT EVO2 First upload: code, electronics... --- Arduino/BROBOT_EVO2/BROBOT_EVO2.ino | 580 +++ Arduino/BROBOT_EVO2/Control.ino | 181 + Arduino/BROBOT_EVO2/MPU6050.ino | 716 +++ Arduino/BROBOT_EVO2/Network.ino | 144 + Arduino/BROBOT_EVO2/OSC.ino | 304 ++ Arduino/BROBOT_EVO2/Servos.ino | 87 + Hardware/electronics/brobot19.sch | 6404 +++++++++++++++++++++++++++ 7 files changed, 8416 insertions(+) create mode 100644 Arduino/BROBOT_EVO2/BROBOT_EVO2.ino create mode 100644 Arduino/BROBOT_EVO2/Control.ino create mode 100644 Arduino/BROBOT_EVO2/MPU6050.ino create mode 100644 Arduino/BROBOT_EVO2/Network.ino create mode 100644 Arduino/BROBOT_EVO2/OSC.ino create mode 100644 Arduino/BROBOT_EVO2/Servos.ino create mode 100644 Hardware/electronics/brobot19.sch diff --git a/Arduino/BROBOT_EVO2/BROBOT_EVO2.ino b/Arduino/BROBOT_EVO2/BROBOT_EVO2.ino new file mode 100644 index 0000000..8573539 --- /dev/null +++ b/Arduino/BROBOT_EVO2/BROBOT_EVO2.ino @@ -0,0 +1,580 @@ +// BROBOT EVO 2 by JJROBOTS +// SELF BALANCE ARDUINO ROBOT WITH STEPPER MOTORS +// JJROBOTS BROBOT KIT: (Arduino Leonardo + BROBOT ELECTRONIC BRAIN SHIELD + STEPPER MOTOR drivers) +// This code is prepared for new BROBOT shield with ESP8266 Wifi module +// This code doesn´t need external libraries +// Author: JJROBOTS.COM +// Date: 02/09/2014 +// Updated: 08/03/2017 +// Version: 2.8 +// License: GPL v2 +// Project URL: http://jjrobots.com/b-robot (Features,documentation,build instructions,how it works, SHOP,...) +// New updates: +// - New default parameters specially tuned for BROBOT EVO 2 version +// - New Move mode with position control (for externally programming the robot) +// - New telemtry packets send to TELEMETRY IP for monitoring Battery, Angle, ... (old battery packets for touch osc not working now) +// - Default telemetry server is 192.168.4.2 (first client connected to the robot) +// Get the free android app (jjrobots) from google play. For IOS users you need to use TouchOSC App + special template (info on jjrobots page) +// Thanks to our users on the forum for the new ideas. Specially sasa999, KomX, ... + +// The board needs at least 10-15 seconds with no motion (robot steady) at beginning to give good values... +// MPU6050 IMU connected via I2C bus. Angle estimation using complementary filter (fusion between gyro and accel) +// Angle calculations and control part is running at 100Hz + +// The robot is OFF when the angle is high (robot is horizontal). When you start raising the robot it +// automatically switch ON and start a RAISE UP procedure. +// You could RAISE UP the robot also with the robot arm servo (Servo button on the interface) +// To switch OFF the robot you could manually put the robot down on the floor (horizontal) + +// We use a standard PID controllers (Proportional, Integral derivative controller) for robot stability +// More info on the project page: How it works page at jjrobots.com +// We have a PI controller for speed control and a PD controller for stability (robot angle) +// The output of the control (motors speed) is integrated so it´s really an acceleration not an speed. + +// We control the robot from a WIFI module using OSC standard UDP messages +// You need an OSC app to control de robot (Custom free JJRobots APP for android, and TouchOSC APP for IOS) +// Join the module Wifi Access Point (by default: JJROBOTS_XX) with your Smartphone/Tablet... +// Wifi password: 87654321 +// For TouchOSC users (IOS): Install the BROBOT layout into the OSC app (Touch OSC) and start play! (read the project page) +// OSC controls: +// fader1: Throttle (0.0-1.0) OSC message: /1/fader1 +// fader2: Steering (0.0-1.0) OSC message: /1/fader2 +// push1: Move servo arm (and robot raiseup) OSC message /1/push1 +// if you enable the touchMessage on TouchOSC options, controls return to center automatically when you lift your fingers +// PRO mode (PRO button). On PRO mode steering and throttle are more aggressive +// PAGE2: PID adjustements [optional][dont touch if you dont know what you are doing...;-) ] + +#include + +// Uncomment this lines to connect to an external Wifi router (join an existing Wifi network) +//#define EXTERNAL_WIFI +//#define WIFI_SSID "YOUR_WIFI" +//#define WIFI_PASSWORD "YOUR_PASSWORD" +//#define WIFI_IP "192.168.1.101" // Force ROBOT IP +//#define TELEMETRY "192.168.1.38" // Tlemetry server port 2223 + +#define TELEMETRY "192.168.4.2" // Default telemetry server (first client) port 2223 + +// NORMAL MODE PARAMETERS (MAXIMUN SETTINGS) +#define MAX_THROTTLE 550 +#define MAX_STEERING 140 +#define MAX_TARGET_ANGLE 14 + +// PRO MODE = MORE AGGRESSIVE (MAXIMUN SETTINGS) +#define MAX_THROTTLE_PRO 860 +#define MAX_STEERING_PRO 280 +#define MAX_TARGET_ANGLE_PRO 32 + +// Default control terms for EVO 2 +#define KP 0.32 +#define KD 0.050 +#define KP_THROTTLE 0.075 +#define KI_THROTTLE 0.1 +#define KP_POSITION 0.06 +#define KD_POSITION 0.45 +//#define KI_POSITION 0.02 + +// Control gains for raiseup (the raiseup movement requiere special control parameters) +#define KP_RAISEUP 0.1 +#define KD_RAISEUP 0.16 +#define KP_THROTTLE_RAISEUP 0 // No speed control on raiseup +#define KI_THROTTLE_RAISEUP 0.0 + +#define MAX_CONTROL_OUTPUT 500 +#define ITERM_MAX_ERROR 30 // Iterm windup constants for PI control +#define ITERM_MAX 10000 + +#define ANGLE_OFFSET -1.0 // Offset angle for balance (to compensate robot own weitght distribution) + +// Servo definitions +#define SERVO_AUX_NEUTRO 1500 // Servo neutral position +#define SERVO_MIN_PULSEWIDTH 700 +#define SERVO_MAX_PULSEWIDTH 2500 + +// Telemetry +#define TELEMETRY_BATTERY 1 +#define TELEMETRY_ANGLE 1 +//#define TELEMETRY_DEBUG 1 // Dont use TELEMETRY_ANGLE and TELEMETRY_DEBUG at the same time! + +#define ZERO_SPEED 65535 +#define MAX_ACCEL 15 // Maximun motor acceleration (MAX RECOMMENDED VALUE: 20) (default:15) + +#define MICROSTEPPING 16 // 8 or 16 for 1/8 or 1/16 driver microstepping (default:16) + +#define DEBUG 0 // 0 = No debug info (default) DEBUG 1 for console output + +// AUX definitions +#define CLR(x,y) (x&=(~(1< 0 + delay(9000); +#else + delay(1000); +#endif + Serial.println("BROBOT by JJROBOTS v2.8"); + + delay(200); + Serial.println("Don't move for 10 sec..."); + MPU6050_setup(); // setup MPU6050 IMU + delay(500); + + // With the new ESP8266 WIFI MODULE WE NEED TO MAKE AN INITIALIZATION PROCESS + Serial.println("WIFI init"); + Serial1.flush(); + Serial1.print("+++"); // To ensure we exit the transparent transmision mode + delay(100); + ESPsendCommand("AT", "OK", 1); + ESPsendCommand("AT+RST", "OK", 2); // ESP Wifi module RESET + ESPwait("ready", 6); + ESPsendCommand("AT+GMR", "OK", 5); + +#ifdef EXTERNAL_WIFI + ESPsendCommand("AT+CWQAP", "OK", 3); + ESPsendCommand("AT+CWMODE=1", "OK", 3); + //String auxCommand = (String)"AT+CWJAP="+WIFI_SSID+","+WIFI_PASSWORD; + char auxCommand[90] = "AT+CWJAP=\""; + strcat(auxCommand, WIFI_SSID); + strcat(auxCommand, "\",\""); + strcat(auxCommand, WIFI_PASSWORD); + strcat(auxCommand, "\""); + ESPsendCommand(auxCommand, "OK", 14); +#ifdef WIFI_IP + strcpy(auxCommand, "AT+CIPSTA=\""); + strcat(auxCommand, WIFI_IP); + strcat(auxCommand, "\""); + ESPsendCommand(auxCommand, "OK", 4); +#endif + ESPsendCommand("AT+CIPSTA?", "OK", 4); +#else // Deafault : we generate a wifi network + Serial1.println("AT+CIPSTAMAC?"); + ESPgetMac(); + //Serial.print("MAC:"); + //Serial.println(MAC); + delay(200); + ESPsendCommand("AT+CWQAP", "OK", 3); + ESPsendCommand("AT+CWMODE=2", "OK", 3); // Soft AP mode + // Generate Soft AP. SSID=JJROBOTS, PASS=87654321 + char *cmd = "AT+CWSAP=\"JJROBOTS_XX\",\"87654321\",5,3"; + // Update XX characters with MAC address (last 2 characters) + cmd[19] = MAC[10]; + cmd[20] = MAC[11]; + ESPsendCommand(cmd, "OK", 6); +#endif + // Start UDP SERVER on port 2222, telemetry port 2223 + //Serial.println("Start UDP server"); + //ESPsendCommand("AT+CIPMUX=0", "OK", 3); // Single connection mode + //ESPsendCommand("AT+CIPMODE=1", "OK", 3); // Transparent mode + //char Telemetry[80]; + //strcpy(Telemetry,"AT+CIPSTART=\"UDP\",\""); + //strcat(Telemetry,TELEMETRY); + //strcat(Telemetry,"\",2223,2222,0"); + //ESPsendCommand(Telemetry, "OK", 3); + + // Start TCP SERVER + ESPsendCommand("AT+CIPMUX=1", "OK", 3); // Single connection mode + ESPsendCommand("AT+CIPMODE=1", "OK", 3); // Transparent mode + ESPsendCommand("AT+CIPSERVER=1,2222", "OK", 3); // TCP server + + // Calibrate gyros + MPU6050_calibrate(); + + ESPsendCommand("AT+CIPSEND", ">", 2); // Start transmission (transparent mode) + + // Init servos + Serial.println("Servo init"); + BROBOT_initServo(); + BROBOT_moveServo1(SERVO_AUX_NEUTRO); + + // STEPPER MOTORS INITIALIZATION + Serial.println("Stepers init"); + // MOTOR1 => TIMER1 + TCCR1A = 0; // Timer1 CTC mode 4, OCxA,B outputs disconnected + TCCR1B = (1 << WGM12) | (1 << CS11); // Prescaler=8, => 2Mhz + OCR1A = ZERO_SPEED; // Motor stopped + dir_M1 = 0; + TCNT1 = 0; + + // MOTOR2 => TIMER3 + TCCR3A = 0; // Timer3 CTC mode 4, OCxA,B outputs disconnected + TCCR3B = (1 << WGM32) | (1 << CS31); // Prescaler=8, => 2Mhz + OCR3A = ZERO_SPEED; // Motor stopped + dir_M2 = 0; + TCNT3 = 0; + delay(200); + + // Enable stepper drivers and TIMER interrupts + digitalWrite(4, LOW); // Enable stepper drivers + // Enable TIMERs interrupts + TIMSK1 |= (1 << OCIE1A); // Enable Timer1 interrupt + TIMSK3 |= (1 << OCIE1A); // Enable Timer1 interrupt + + // Little motor vibration and servo move to indicate that robot is ready + for (uint8_t k = 0; k < 5; k++) + { + setMotorSpeedM1(5); + setMotorSpeedM2(5); + BROBOT_moveServo1(SERVO_AUX_NEUTRO + 100); + delay(200); + setMotorSpeedM1(-5); + setMotorSpeedM2(-5); + BROBOT_moveServo1(SERVO_AUX_NEUTRO - 100); + delay(200); + } + BROBOT_moveServo1(SERVO_AUX_NEUTRO); + + #if TELEMETRY_BATTERY==1 + BatteryValue = BROBOT_readBattery(true); + Serial.print("BATT:"); + Serial.println(BatteryValue); +#endif + + Serial.println("Start..."); + timer_old = micros(); +} + + +// MAIN LOOP +void loop() +{ + OSC_MsgRead(); // Read UDP OSC messages + if (OSCnewMessage) + { + OSCnewMessage = 0; + if (OSCpage == 1) // Get commands from user (PAGE1 are user commands: throttle, steering...) + { + if (modifing_control_parameters) // We came from the settings screen + { + OSCfader[0] = 0.5; // default neutral values + OSCfader[1] = 0.5; + OSCtoggle[0] = 0; // Normal mode + mode = 0; + modifing_control_parameters = false; + } + + if (OSCmove_mode) + { + //Serial.print("M "); + //Serial.print(OSCmove_speed); + //Serial.print(" "); + //Serial.print(OSCmove_steps1); + //Serial.print(","); + //Serial.println(OSCmove_steps2); + positionControlMode = true; + OSCmove_mode = false; + target_steps1 = steps1 + OSCmove_steps1; + target_steps2 = steps2 + OSCmove_steps2; + } + else + { + positionControlMode = false; + throttle = (OSCfader[0] - 0.5) * max_throttle; + // We add some exponential on steering to smooth the center band + steering = OSCfader[1] - 0.5; + if (steering > 0) + steering = (steering * steering + 0.5 * steering) * max_steering; + else + steering = (-steering * steering + 0.5 * steering) * max_steering; + } + + if ((mode == 0) && (OSCtoggle[0])) + { + // Change to PRO mode + max_throttle = MAX_THROTTLE_PRO; + max_steering = MAX_STEERING_PRO; + max_target_angle = MAX_TARGET_ANGLE_PRO; + mode = 1; + } + if ((mode == 1) && (OSCtoggle[0] == 0)) + { + // Change to NORMAL mode + max_throttle = MAX_THROTTLE; + max_steering = MAX_STEERING; + max_target_angle = MAX_TARGET_ANGLE; + mode = 0; + } + } + else if (OSCpage == 2) { // OSC page 2 + // Check for new user control parameters + readControlParameters(); + } +#if DEBUG==1 + Serial.print(throttle); + Serial.print(" "); + Serial.println(steering); +#endif + } // End new OSC message + + timer_value = micros(); + + // New IMU data? + if (MPU6050_newData()) + { + MPU6050_read_3axis(); + loop_counter++; + slow_loop_counter++; + dt = (timer_value - timer_old) * 0.000001; // dt in seconds + timer_old = timer_value; + + angle_adjusted_Old = angle_adjusted; + // Get new orientation angle from IMU (MPU6050) + angle_adjusted = MPU6050_getAngle(dt) + ANGLE_OFFSET; + +#if DEBUG==1 + Serial.print(dt); + Serial.print(" "); + Serial.println(angle_adjusted); +#endif + //Serial.print("\t"); + + // We calculate the estimated robot speed: + // Estimated_Speed = angular_velocity_of_stepper_motors(combined) - angular_velocity_of_robot(angle measured by IMU) + actual_robot_speed = (speed_M1 + speed_M2) / 2; // Positive: forward + + int16_t angular_velocity = (angle_adjusted - angle_adjusted_Old) * 25.0; // 25 is an empirical extracted factor to adjust for real units + int16_t estimated_speed = -actual_robot_speed + angular_velocity; + estimated_speed_filtered = estimated_speed_filtered * 0.9 + (float)estimated_speed * 0.1; // low pass filter on estimated speed + +#if DEBUG==2 + Serial.print(angle_adjusted); + Serial.print(" "); + Serial.println(estimated_speed_filtered); +#endif + + if (positionControlMode) + { + // POSITION CONTROL. INPUT: Target steps for each motor. Output: motors speed + motor1_control = positionPDControl(steps1, target_steps1, Kp_position, Kd_position, speed_M1); + motor2_control = positionPDControl(steps2, target_steps2, Kp_position, Kd_position, speed_M2); + + // Convert from motor position control to throttle / steering commands + throttle = (motor1_control + motor2_control) / 2; + throttle = constrain(throttle, -190, 190); + steering = motor2_control - motor1_control; + steering = constrain(steering, -50, 50); + } + + // ROBOT SPEED CONTROL: This is a PI controller. + // input:user throttle(robot speed), variable: estimated robot speed, output: target robot angle to get the desired speed + target_angle = speedPIControl(dt, estimated_speed_filtered, throttle, Kp_thr, Ki_thr); + target_angle = constrain(target_angle, -max_target_angle, max_target_angle); // limited output + + +#if DEBUG==3 + Serial.print(angle_adjusted); + Serial.print(" "); + Serial.print(estimated_speed_filtered); + Serial.print(" "); + Serial.println(target_angle); +#endif + + // Stability control (100Hz loop): This is a PD controller. + // input: robot target angle(from SPEED CONTROL), variable: robot angle, output: Motor speed + // We integrate the output (sumatory), so the output is really the motor acceleration, not motor speed. + control_output += stabilityPDControl(dt, angle_adjusted, target_angle, Kp, Kd); + control_output = constrain(control_output, -MAX_CONTROL_OUTPUT, MAX_CONTROL_OUTPUT); // Limit max output from control + + // The steering part from the user is injected directly to the output + motor1 = control_output + steering; + motor2 = control_output - steering; + + // Limit max speed (control output) + motor1 = constrain(motor1, -MAX_CONTROL_OUTPUT, MAX_CONTROL_OUTPUT); + motor2 = constrain(motor2, -MAX_CONTROL_OUTPUT, MAX_CONTROL_OUTPUT); + + int angle_ready; + if (OSCpush[0]) // If we press the SERVO button we start to move + angle_ready = 80; + else + angle_ready = 74; // Default angle + if ((angle_adjusted < angle_ready) && (angle_adjusted > -angle_ready)) // Is robot ready (upright?) + { + // NORMAL MODE + digitalWrite(4, LOW); // Motors enable + // NOW we send the commands to the motors + setMotorSpeedM1(motor1); + setMotorSpeedM2(motor2); + } + else // Robot not ready (flat), angle > angle_ready => ROBOT OFF + { + digitalWrite(4, HIGH); // Disable motors + setMotorSpeedM1(0); + setMotorSpeedM2(0); + PID_errorSum = 0; // Reset PID I term + Kp = KP_RAISEUP; // CONTROL GAINS FOR RAISE UP + Kd = KD_RAISEUP; + Kp_thr = KP_THROTTLE_RAISEUP; + Ki_thr = KI_THROTTLE_RAISEUP; + // RESET steps + steps1 = 0; + steps2 = 0; + } + + // Push1 Move servo arm + if (OSCpush[0]) // Move arm + { + if (angle_adjusted > -40) + BROBOT_moveServo1(SERVO_MIN_PULSEWIDTH); + else + BROBOT_moveServo1(SERVO_MAX_PULSEWIDTH); + } + else + BROBOT_moveServo1(SERVO_AUX_NEUTRO); + + // Normal condition? + if ((angle_adjusted < 56) && (angle_adjusted > -56)) + { + Kp = Kp_user; // Default user control gains + Kd = Kd_user; + Kp_thr = Kp_thr_user; + Ki_thr = Ki_thr_user; + } + else // We are in the raise up procedure => we use special control parameters + { + Kp = KP_RAISEUP; // CONTROL GAINS FOR RAISE UP + Kd = KD_RAISEUP; + Kp_thr = KP_THROTTLE_RAISEUP; + Ki_thr = KI_THROTTLE_RAISEUP; + } + + } // End of new IMU data + + // Medium loop 7.5Hz + if (loop_counter >= 15) + { + loop_counter = 0; + // Telemetry here? +#if TELEMETRY_ANGLE==1 + char auxS[25]; + int ang_out = constrain(int(angle_adjusted * 10),-900,900); + sprintf(auxS, "$tA,%+04d", ang_out); + Serial1.println(auxS); +#endif +#if TELEMETRY_DEBUG==1 + char auxS[50]; + sprintf(auxS, "$tD,%d,%d,%ld", int(angle_adjusted * 10), int(estimated_speed_filtered), steps1); + Serial1.println(auxS); +#endif + + } // End of medium loop + else if (slow_loop_counter >= 100) // 1Hz + { + slow_loop_counter = 0; + // Read status +#if TELEMETRY_BATTERY==1 + BatteryValue = (BatteryValue + BROBOT_readBattery(false)) / 2; + sendBattery_counter++; + if (sendBattery_counter >= 3) { //Every 3 seconds we send a message + sendBattery_counter = 0; + Serial.print("B"); + Serial.println(BatteryValue); + char auxS[25]; + sprintf(auxS, "$tB,%04d", BatteryValue); + Serial1.println(auxS); + } +#endif + } // End of slow loop +} + diff --git a/Arduino/BROBOT_EVO2/Control.ino b/Arduino/BROBOT_EVO2/Control.ino new file mode 100644 index 0000000..d2a0803 --- /dev/null +++ b/Arduino/BROBOT_EVO2/Control.ino @@ -0,0 +1,181 @@ +// BROBOT EVO 2 by JJROBOTS +// SELF BALANCE ARDUINO ROBOT WITH STEPPER MOTORS +// License: GPL v2 +// Control functions (PID controls, Steppers control...) + +// PD controller implementation(Proportional, derivative). DT in seconds +float stabilityPDControl(float DT, float input, float setPoint, float Kp, float Kd) +{ + float error; + float output; + + error = setPoint - input; + + // Kd is implemented in two parts + // The biggest one using only the input (sensor) part not the SetPoint input-input(t-1). + // And the second using the setpoint to make it a bit more agressive setPoint-setPoint(t-1) + float Kd_setPoint = constrain((setPoint - setPointOld), -8, 8); // We limit the input part... + output = Kp * error + (Kd * Kd_setPoint - Kd * (input - PID_errorOld)) / DT; + //Serial.print(Kd*(error-PID_errorOld));Serial.print("\t"); + //PID_errorOld2 = PID_errorOld; + PID_errorOld = input; // error for Kd is only the input component + setPointOld = setPoint; + return (output); +} + + +// PI controller implementation (Proportional, integral). DT in seconds +float speedPIControl(float DT, int16_t input, int16_t setPoint, float Kp, float Ki) +{ + int16_t error; + float output; + + error = setPoint - input; + PID_errorSum += constrain(error, -ITERM_MAX_ERROR, ITERM_MAX_ERROR); + PID_errorSum = constrain(PID_errorSum, -ITERM_MAX, ITERM_MAX); + + //Serial.println(PID_errorSum); + + output = Kp * error + Ki * PID_errorSum * DT; // DT is in miliseconds... + return (output); +} + + +float positionPDControl(long actualPos, long setPointPos, float Kpp, float Kdp, int16_t speedM) +{ + float output; + float P; + + P = constrain(Kpp * float(setPointPos - actualPos), -115, 115); // Limit command + output = P + Kdp * float(speedM); + return (output); +} + +// TIMER 1 : STEPPER MOTOR1 SPEED CONTROL +ISR(TIMER1_COMPA_vect) +{ + if (dir_M1 == 0) // If we are not moving we dont generate a pulse + return; + // We generate 1us STEP pulse + SET(PORTE, 6); // STEP MOTOR 1 + //delay_1us(); + if (dir_M1 > 0) + steps1--; + else + steps1++; + CLR(PORTE, 6); +} +// TIMER 3 : STEPPER MOTOR2 SPEED CONTROL +ISR(TIMER3_COMPA_vect) +{ + if (dir_M2 == 0) // If we are not moving we dont generate a pulse + return; + // We generate 1us STEP pulse + SET(PORTD, 6); // STEP MOTOR 2 + //delay_1us(); + if (dir_M2 > 0) + steps2--; + else + steps2++; + CLR(PORTD, 6); +} + + +// Set speed of Stepper Motor1 +// tspeed could be positive or negative (reverse) +void setMotorSpeedM1(int16_t tspeed) +{ + long timer_period; + int16_t speed; + + // Limit max speed? + + // WE LIMIT MAX ACCELERATION of the motors + if ((speed_M1 - tspeed) > MAX_ACCEL) + speed_M1 -= MAX_ACCEL; + else if ((speed_M1 - tspeed) < -MAX_ACCEL) + speed_M1 += MAX_ACCEL; + else + speed_M1 = tspeed; + +#if MICROSTEPPING==16 + speed = speed_M1 * 50; // Adjust factor from control output speed to real motor speed in steps/second +#else + speed = speed_M1 * 25; // 1/8 Microstepping +#endif + + if (speed == 0) + { + timer_period = ZERO_SPEED; + dir_M1 = 0; + } + else if (speed > 0) + { + timer_period = 2000000 / speed; // 2Mhz timer + dir_M1 = 1; + SET(PORTB, 4); // DIR Motor 1 (Forward) + } + else + { + timer_period = 2000000 / -speed; + dir_M1 = -1; + CLR(PORTB, 4); // Dir Motor 1 + } + if (timer_period > 65535) // Check for minimun speed (maximun period without overflow) + timer_period = ZERO_SPEED; + + OCR1A = timer_period; + // Check if we need to reset the timer... + if (TCNT1 > OCR1A) + TCNT1 = 0; +} + +// Set speed of Stepper Motor2 +// tspeed could be positive or negative (reverse) +void setMotorSpeedM2(int16_t tspeed) +{ + long timer_period; + int16_t speed; + + // Limit max speed? + + // WE LIMIT MAX ACCELERATION of the motors + if ((speed_M2 - tspeed) > MAX_ACCEL) + speed_M2 -= MAX_ACCEL; + else if ((speed_M2 - tspeed) < -MAX_ACCEL) + speed_M2 += MAX_ACCEL; + else + speed_M2 = tspeed; + +#if MICROSTEPPING==16 + speed = speed_M2 * 50; // Adjust factor from control output speed to real motor speed in steps/second +#else + speed = speed_M2 * 25; // 1/8 Microstepping +#endif + + if (speed == 0) + { + timer_period = ZERO_SPEED; + dir_M2 = 0; + } + else if (speed > 0) + { + timer_period = 2000000 / speed; // 2Mhz timer + dir_M2 = 1; + CLR(PORTC, 6); // Dir Motor2 (Forward) + } + else + { + timer_period = 2000000 / -speed; + dir_M2 = -1; + SET(PORTC, 6); // DIR Motor 2 + } + if (timer_period > 65535) // Check for minimun speed (maximun period without overflow) + timer_period = ZERO_SPEED; + + OCR3A = timer_period; + // Check if we need to reset the timer... + if (TCNT3 > OCR3A) + TCNT3 = 0; +} + diff --git a/Arduino/BROBOT_EVO2/MPU6050.ino b/Arduino/BROBOT_EVO2/MPU6050.ino new file mode 100644 index 0000000..d126a70 --- /dev/null +++ b/Arduino/BROBOT_EVO2/MPU6050.ino @@ -0,0 +1,716 @@ +// BROBOT EVO 2 by JJROBOTS +// SELF BALANCE ARDUINO ROBOT WITH STEPPER MOTORS +// License: GPL v2 +// MPU6050 IMU code +// Read the accel and gyro registers and calculate a complementary filter for sensor fusion between gyros and accel + +// Code based on arduino.cc MPU6050 sample +// Open Source / Public Domain +// +// Documentation:"MPU-6000 and MPU-6050 Register Map and Descriptions": RM-MPU-6000A.pdf + +// MPU6050 Register map +#define MPU6050_AUX_VDDIO 0x01 // R/W +#define MPU6050_SMPLRT_DIV 0x19 // R/W +#define MPU6050_CONFIG 0x1A // R/W +#define MPU6050_GYRO_CONFIG 0x1B // R/W +#define MPU6050_ACCEL_CONFIG 0x1C // R/W +#define MPU6050_FF_THR 0x1D // R/W +#define MPU6050_FF_DUR 0x1E // R/W +#define MPU6050_MOT_THR 0x1F // R/W +#define MPU6050_MOT_DUR 0x20 // R/W +#define MPU6050_ZRMOT_THR 0x21 // R/W +#define MPU6050_ZRMOT_DUR 0x22 // R/W +#define MPU6050_FIFO_EN 0x23 // R/W +#define MPU6050_I2C_MST_CTRL 0x24 // R/W +#define MPU6050_I2C_SLV0_ADDR 0x25 // R/W +#define MPU6050_I2C_SLV0_REG 0x26 // R/W +#define MPU6050_I2C_SLV0_CTRL 0x27 // R/W +#define MPU6050_I2C_SLV1_ADDR 0x28 // R/W +#define MPU6050_I2C_SLV1_REG 0x29 // R/W +#define MPU6050_I2C_SLV1_CTRL 0x2A // R/W +#define MPU6050_I2C_SLV2_ADDR 0x2B // R/W +#define MPU6050_I2C_SLV2_REG 0x2C // R/W +#define MPU6050_I2C_SLV2_CTRL 0x2D // R/W +#define MPU6050_I2C_SLV3_ADDR 0x2E // R/W +#define MPU6050_I2C_SLV3_REG 0x2F // R/W +#define MPU6050_I2C_SLV3_CTRL 0x30 // R/W +#define MPU6050_I2C_SLV4_ADDR 0x31 // R/W +#define MPU6050_I2C_SLV4_REG 0x32 // R/W +#define MPU6050_I2C_SLV4_DO 0x33 // R/W +#define MPU6050_I2C_SLV4_CTRL 0x34 // R/W +#define MPU6050_I2C_SLV4_DI 0x35 // R +#define MPU6050_I2C_MST_STATUS 0x36 // R +#define MPU6050_INT_PIN_CFG 0x37 // R/W +#define MPU6050_INT_ENABLE 0x38 // R/W +#define MPU6050_INT_STATUS 0x3A // R +#define MPU6050_ACCEL_XOUT_H 0x3B // R +#define MPU6050_ACCEL_XOUT_L 0x3C // R +#define MPU6050_ACCEL_YOUT_H 0x3D // R +#define MPU6050_ACCEL_YOUT_L 0x3E // R +#define MPU6050_ACCEL_ZOUT_H 0x3F // R +#define MPU6050_ACCEL_ZOUT_L 0x40 // R +#define MPU6050_TEMP_OUT_H 0x41 // R +#define MPU6050_TEMP_OUT_L 0x42 // R +#define MPU6050_GYRO_XOUT_H 0x43 // R +#define MPU6050_GYRO_XOUT_L 0x44 // R +#define MPU6050_GYRO_YOUT_H 0x45 // R +#define MPU6050_GYRO_YOUT_L 0x46 // R +#define MPU6050_GYRO_ZOUT_H 0x47 // R +#define MPU6050_GYRO_ZOUT_L 0x48 // R +#define MPU6050_EXT_SENS_DATA_00 0x49 // R +#define MPU6050_EXT_SENS_DATA_01 0x4A // R +#define MPU6050_EXT_SENS_DATA_02 0x4B // R +#define MPU6050_EXT_SENS_DATA_03 0x4C // R +#define MPU6050_EXT_SENS_DATA_04 0x4D // R +#define MPU6050_EXT_SENS_DATA_05 0x4E // R +#define MPU6050_EXT_SENS_DATA_06 0x4F // R +#define MPU6050_EXT_SENS_DATA_07 0x50 // R +#define MPU6050_EXT_SENS_DATA_08 0x51 // R +#define MPU6050_EXT_SENS_DATA_09 0x52 // R +#define MPU6050_EXT_SENS_DATA_10 0x53 // R +#define MPU6050_EXT_SENS_DATA_11 0x54 // R +#define MPU6050_EXT_SENS_DATA_12 0x55 // R +#define MPU6050_EXT_SENS_DATA_13 0x56 // R +#define MPU6050_EXT_SENS_DATA_14 0x57 // R +#define MPU6050_EXT_SENS_DATA_15 0x58 // R +#define MPU6050_EXT_SENS_DATA_16 0x59 // R +#define MPU6050_EXT_SENS_DATA_17 0x5A // R +#define MPU6050_EXT_SENS_DATA_18 0x5B // R +#define MPU6050_EXT_SENS_DATA_19 0x5C // R +#define MPU6050_EXT_SENS_DATA_20 0x5D // R +#define MPU6050_EXT_SENS_DATA_21 0x5E // R +#define MPU6050_EXT_SENS_DATA_22 0x5F // R +#define MPU6050_EXT_SENS_DATA_23 0x60 // R +#define MPU6050_MOT_DETECT_STATUS 0x61 // R +#define MPU6050_I2C_SLV0_DO 0x63 // R/W +#define MPU6050_I2C_SLV1_DO 0x64 // R/W +#define MPU6050_I2C_SLV2_DO 0x65 // R/W +#define MPU6050_I2C_SLV3_DO 0x66 // R/W +#define MPU6050_I2C_MST_DELAY_CTRL 0x67 // R/W +#define MPU6050_SIGNAL_PATH_RESET 0x68 // R/W +#define MPU6050_MOT_DETECT_CTRL 0x69 // R/W +#define MPU6050_USER_CTRL 0x6A // R/W +#define MPU6050_PWR_MGMT_1 0x6B // R/W +#define MPU6050_PWR_MGMT_2 0x6C // R/W +#define MPU6050_FIFO_COUNTH 0x72 // R/W +#define MPU6050_FIFO_COUNTL 0x73 // R/W +#define MPU6050_FIFO_R_W 0x74 // R/W +#define MPU6050_WHO_AM_I 0x75 // R + +// Defines for the bits, to be able to change +// between bit number and binary definition. +// By using the bit number, programming the sensor +// is like programming the AVR microcontroller. +// But instead of using "(1< 65.5 LSB/deg/s + + // Complementary filter + // We integrate the gyro rate value to obtain the angle in the short term and we take the accelerometer angle with a low pass filter in the long term... + angle = 0.99 * (angle + x_gyro_value * dt) + 0.01 * accel_angle; // Time constant = 0.99*0.01(100hz)/(1-0.99) = 0.99, around 1 sec. + + // Gyro bias correction + // We supose that the long term mean of the gyro_value should tend to zero (gyro_offset). This means that the robot is not continuosly rotating. + int16_t correction = constrain(accel_t_gyro.value.x_gyro, x_gyro_offset - 10, x_gyro_offset + 10); // limit corrections... + x_gyro_offset = x_gyro_offset * 0.9995 + correction * 0.0005; // Time constant of this correction is around 20 sec. + + //Serial.print(angle); + //Serial.print(" "); + //Serial.println(x_gyro_offset); + + return angle; +} + +// Calibrate function. Take 100 readings (over 2 seconds) to calculate the gyro offset value. IMU should be steady in this process... +void MPU6050_calibrate() +{ + int i; + long value = 0; + float dev; + int16_t values[100]; + bool gyro_cal_ok = false; + + delay(500); + while (!gyro_cal_ok){ + Serial.println("Gyro calibration... DONT MOVE!"); + // we take 100 measurements in 4 seconds + for (i = 0; i < 100; i++) + { + MPU6050_read_3axis(); + values[i] = accel_t_gyro.value.x_gyro; + value += accel_t_gyro.value.x_gyro; + delay(25); + } + // mean value + value = value / 100; + // calculate the standard deviation + dev = 0; + for (i = 0; i < 100; i++) + dev += (values[i] - value) * (values[i] - value); + dev = sqrt((1 / 100.0) * dev); + Serial.print("offset: "); + Serial.print(value); + Serial.print(" stddev: "); + Serial.println(dev); + if (dev < 50.0) + gyro_cal_ok = true; + else + Serial.println("Repeat, DONT MOVE!"); + } + x_gyro_offset = value; + // Take the first reading of angle from accels + angle = atan2f((float)accel_t_gyro.value.y_accel, (float)accel_t_gyro.value.z_accel) * RAD2GRAD; +} + +void MPU6050_setup() +{ + int error; + uint8_t c; + + error = MPU6050_read(MPU6050_WHO_AM_I, &c, 1); + Serial.print("WHO_AM_I : "); + Serial.print(c, HEX); + Serial.print(", error = "); + Serial.println(error, DEC); + + // RESET chip + MPU6050_write_reg(MPU6050_PWR_MGMT_1, bit(MPU6050_DEVICE_RESET)); + delay(125); + // Clear the 'sleep' bit to start the sensor and select clock source + MPU6050_write_reg (MPU6050_PWR_MGMT_1, 0x01); + //MPU6050_write_reg(MPU6050_PWR_MGMT_1,MPU6050_CLKSEL_Z); + + // Config Gyro scale (500deg/seg) + MPU6050_write_reg(MPU6050_GYRO_CONFIG, MPU6050_FS_SEL_500); + // Config Accel scale (2g) + MPU6050_write_reg(MPU6050_ACCEL_CONFIG, MPU6050_AFS_SEL_2G); + // Config Digital Low Pass Filter 10Hz + MPU6050_write_reg(MPU6050_CONFIG, MPU6050_DLPF_10HZ); + // Set Sample Rate to 100Hz + MPU6050_write_reg(MPU6050_SMPLRT_DIV, 9); // 100Hz : Sample Rate = 1000 / (1 + SMPLRT_DIV) Hz + // Data ready interrupt enable + MPU6050_write_reg(MPU6050_INT_ENABLE, MPU6050_DATA_RDY_EN); + // Clear the 'sleep' bit to start the sensor (and select clock source). + MPU6050_write_reg (MPU6050_PWR_MGMT_1, 0x01); + + // Clear the 'sleep' bit to start the sensor. + //MPU6050_write_reg(MPU6050_PWR_MGMT_1,MPU6050_CLKSEL_Z); + //MPU6050_write_reg (MPU6050_PWR_MGMT_1, 0); +} + +void MPU6050_read_3axis() +{ + int error; + + // read 14 bytes (gyros, temp and accels) + error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro)); + if (error != 0) { + //Serial.print("MPU6050 Error:"); + //Serial.println(error); + } + // swap bytes + SWAP (accel_t_gyro.reg.x_accel_h, accel_t_gyro.reg.x_accel_l); + SWAP (accel_t_gyro.reg.y_accel_h, accel_t_gyro.reg.y_accel_l); + SWAP (accel_t_gyro.reg.z_accel_h, accel_t_gyro.reg.z_accel_l); + SWAP (accel_t_gyro.reg.t_h, accel_t_gyro.reg.t_l); + SWAP (accel_t_gyro.reg.x_gyro_h, accel_t_gyro.reg.x_gyro_l); + SWAP (accel_t_gyro.reg.y_gyro_h, accel_t_gyro.reg.y_gyro_l); + SWAP (accel_t_gyro.reg.z_gyro_h, accel_t_gyro.reg.z_gyro_l); + + /* + // Print the raw acceleration values + Serial.print("ACC:"); + Serial.print(accel_t_gyro.value.x_accel, DEC); + Serial.print(","); + Serial.print(accel_t_gyro.value.y_accel, DEC); + Serial.print(","); + Serial.print(accel_t_gyro.value.z_accel, DEC); + Serial.println(); + + // Print the raw gyro values. + Serial.print("GY:"); + Serial.print(accel_t_gyro.value.x_gyro, DEC); + Serial.print(","); + Serial.print(accel_t_gyro.value.y_gyro, DEC); + Serial.print(","); + Serial.print(accel_t_gyro.value.z_gyro, DEC); + Serial.print(","); + Serial.println(); + */ +} + +void MPU6050_read_1axis() +{ + int error; + + // read X accel + error = MPU6050_read(MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro.reg.x_accel_h, 6); + if (error != 0) { + //Serial.print("MPU6050 Error:"); + //Serial.println(error); + } + // read X gyro + error = MPU6050_read(MPU6050_GYRO_XOUT_H, (uint8_t *) &accel_t_gyro.reg.x_gyro_h, 2); + if (error != 0) { + //Serial.print("MPU6050 Error:"); + //Serial.println(error); + } + SWAP (accel_t_gyro.reg.x_accel_h, accel_t_gyro.reg.y_accel_l); + SWAP (accel_t_gyro.reg.z_accel_h, accel_t_gyro.reg.z_accel_l); + SWAP (accel_t_gyro.reg.x_gyro_h, accel_t_gyro.reg.x_gyro_l); + + // Print values + Serial.print("axis:"); + Serial.print(accel_t_gyro.value.y_accel, DEC); + Serial.print(","); + Serial.println(accel_t_gyro.value.x_gyro, DEC); +} + +// return true on new data available +bool MPU6050_newData() +{ + uint8_t status; + int error; + + error = MPU6050_read(MPU6050_INT_STATUS, &status, 1); + if (error != 0) { + //Serial.print("MPU6050 Error:"); + //Serial.println(error); + } + if (status & (0b00000001)) // Data ready? + return true; + else + return false; +} + +// MPU6050_read n bytes +int MPU6050_read(int start, uint8_t *buffer, int size) +{ + int i, n, error; + + Wire.beginTransmission(MPU6050_I2C_ADDRESS); + n = Wire.write(start); + if (n != 1) + return (-10); + + n = Wire.endTransmission(false); // hold the I2C-bus + if (n != 0) + return (n); + + // Third parameter is true: relase I2C-bus after data is read. + Wire.requestFrom(MPU6050_I2C_ADDRESS, size, true); + i = 0; + while (Wire.available() && i < size) + { + buffer[i++] = Wire.read(); + } + if ( i != size) + return (-11); + + return (0); // return : no error +} + + +// MPU6050_write n bytes +int MPU6050_write(int start, const uint8_t *pData, int size) +{ + int n, error; + + Wire.beginTransmission(MPU6050_I2C_ADDRESS); + n = Wire.write(start); // write the start address + if (n != 1) + return (-20); + + n = Wire.write(pData, size); // write data bytes + if (n != size) + return (-21); + + error = Wire.endTransmission(true); // release the I2C-bus + if (error != 0) + return (error); + + return (0); // return : no error +} + +// -------------------------------------------------------- +// MPU6050_write_reg (only 1 byte) +int MPU6050_write_reg(int reg, uint8_t data) +{ + int error; + + error = MPU6050_write(reg, &data, 1); + + return (error); +} + diff --git a/Arduino/BROBOT_EVO2/Network.ino b/Arduino/BROBOT_EVO2/Network.ino new file mode 100644 index 0000000..7af4c32 --- /dev/null +++ b/Arduino/BROBOT_EVO2/Network.ino @@ -0,0 +1,144 @@ +// BROBOT EVO 2 by JJROBOTS +// SELF BALANCE ARDUINO ROBOT WITH STEPPER MOTORS +// License: GPL v2 +// Network functions (ESP module) + +// Read control PID parameters from user. This is only for advanced users that want to "play" with the controllers... +void readControlParameters() +{ + // Parameters Mode (page2 controls) + // Parameter initialization (first time we enter page2) + if (!modifing_control_parameters) + { + for (uint8_t i = 0; i < 4; i++) + OSCfader[i] = 0.5; + OSCtoggle[0] = 0; + + modifing_control_parameters = true; + Serial1.println("$P2"); + } + // User could adjust KP, KD, KP_THROTTLE and KI_THROTTLE (fadder1,2,3,4) + // Now we need to adjust all the parameters all the times because we dont know what parameter has been moved + Kp_user = KP * 2 * OSCfader[0]; + Kd_user = KD * 2 * OSCfader[1]; + Kp_thr_user = KP_THROTTLE * 2 * OSCfader[2]; + Ki_thr_user = KI_THROTTLE * 2 * OSCfader[3]; + // Send a special telemetry message with the new parameters + char auxS[50]; + sprintf(auxS, "$tP,%d,%d,%d,%d", int(Kp_user * 1000), int(Kd_user * 1000), int(Kp_thr_user * 1000), int(Ki_thr_user * 1000)); + Serial1.println(auxS); + +#if DEBUG>0 + Serial.print("Par: "); + Serial.print(Kp_user); + Serial.print(" "); + Serial.print(Kd_user); + Serial.print(" "); + Serial.print(Kp_thr_user); + Serial.print(" "); + Serial.println(Ki_thr_user); +#endif + + // Kill robot => Sleep + while (OSCtoggle[0] == 1) + { + //Reset external parameters + PID_errorSum = 0; + timer_old = millis(); + setMotorSpeedM1(0); + setMotorSpeedM2(0); + digitalWrite(4, HIGH); // Disable motors + OSC_MsgRead(); + } +} + + +int ESPwait(String stopstr, int timeout_secs) +{ + String response; + bool found = false; + char c; + long timer_init; + long timer; + + timer_init = millis(); + while (!found) { + timer = millis(); + if (((timer - timer_init) / 1000) > timeout_secs) { // Timeout? + Serial.println("!Timeout!"); + return 0; // timeout + } + if (Serial1.available()) { + c = Serial1.read(); + Serial.print(c); + response += c; + if (response.endsWith(stopstr)) { + found = true; + delay(10); + Serial1.flush(); + Serial.println(); + } + } // end Serial1_available() + } // end while (!found) + return 1; +} + +// getMacAddress from ESP wifi module +int ESPgetMac() +{ + char c1, c2; + bool timeout = false; + long timer_init; + long timer; + uint8_t state = 0; + uint8_t index = 0; + + MAC = ""; + timer_init = millis(); + while (!timeout) { + timer = millis(); + if (((timer - timer_init) / 1000) > 5) // Timeout? + timeout = true; + if (Serial1.available()) { + c2 = c1; + c1 = Serial1.read(); + Serial.print(c1); + switch (state) { + case 0: + if (c1 == ':') + state = 1; + break; + case 1: + if (c1 == '\r') { + MAC.toUpperCase(); + state = 2; + } + else { + if ((c1 != '"') && (c1 != ':')) + MAC += c1; // Uppercase + } + break; + case 2: + if ((c2 == 'O') && (c1 == 'K')) { + Serial.println(); + Serial1.flush(); + return 1; // Ok + } + break; + } // end switch + } // Serial_available + } // while (!timeout) + Serial.println("!Timeout!"); + Serial1.flush(); + return -1; // timeout +} + +int ESPsendCommand(char *command, String stopstr, int timeout_secs) +{ + Serial1.println(command); + ESPwait(stopstr, timeout_secs); + delay(250); +} + + + diff --git a/Arduino/BROBOT_EVO2/OSC.ino b/Arduino/BROBOT_EVO2/OSC.ino new file mode 100644 index 0000000..d61592f --- /dev/null +++ b/Arduino/BROBOT_EVO2/OSC.ino @@ -0,0 +1,304 @@ +// BROBOT EVO 2 by JJROBOTS +// SELF BALANCE ARDUINO ROBOT WITH STEPPER MOTORS +// License: GPL v2 +// OSC functions (OSC = Open Sound Control protocol) + +// OSC Messages read: OSC: /page/command parameters +// FADER (1,2,3,4) Ex: /1/fader1 f, XXXX => lenght:20, Param: float (0.0-1.0) +// XY (1,2) Ex: /1/xy1 f,f, XXXXXXXX => length: 24 Params: float,float (0.0-1.0) +// PUSH (1,2,3,4) Ex: /1/push1 f, XXXX => length:20 Param: float +// TOGGLE (1,2,3,4) Ex: /1/toggle1 f, XXXX => length:20 Param: float +// MOVE Ex: /1/m XXXX XXXX XXXX => length:16 Params: speed, steps1, steps2 (all float) +// +// OSC Message send: +// string to send + param (float)[last 4 bytes] + + +// for DEBUG uncomment this lines... +//#define OSCDEBUG 3 + + +char UDPBuffer[8]; // input message buffer + +// OSC message internal variables +unsigned char OSCreadStatus; +unsigned char OSCreadCounter; +unsigned char OSCreadNumParams; +unsigned char OSCcommandType; +unsigned char OSCtouchMessage; + + +// ------- OSC functions ----------------------------------------- + +// Aux functions +float OSC_extractParamFloat(uint8_t pos) { + union { + unsigned char Buff[4]; + float d; + } u; + + u.Buff[0] = (unsigned char)UDPBuffer[pos]; + u.Buff[1] = (unsigned char)UDPBuffer[pos + 1]; + u.Buff[2] = (unsigned char)UDPBuffer[pos + 2]; + u.Buff[3] = (unsigned char)UDPBuffer[pos + 3]; + return (u.d); +} + +int16_t OSC_extractParamInt(uint8_t pos) { + union { + unsigned char Buff[2]; + int16_t d; + } u; + + u.Buff[1] = (unsigned char)UDPBuffer[pos]; + u.Buff[0] = (unsigned char)UDPBuffer[pos + 1]; + return (u.d); +} + + +void OSC_init() +{ + OSCreadStatus = 0; + OSCreadCounter = 0; + OSCreadNumParams = 0; + OSCcommandType = 0; + OSCfader[0] = 0.5; + OSCfader[1] = 0.5; + OSCfader[2] = 0.5; + OSCfader[3] = 0.5; +} + +void OSC_MsgSend(char *c, unsigned char msgSize, float p) +{ + uint8_t i; + union { + unsigned char Buff[4]; + float d; + } u; + + // We copy the param in the last 4 bytes + u.d = p; + c[msgSize - 4] = u.Buff[3]; + c[msgSize - 3] = u.Buff[2]; + c[msgSize - 2] = u.Buff[1]; + c[msgSize - 1] = u.Buff[0]; + for (i = 0; i < msgSize; i++) + { + Serial1.write((uint8_t)c[i]); + //Serial.write((uint8_t)c[i]); + } +} + +void OSC_MsgRead() +{ + uint8_t i; + uint8_t tmp; + float value; + float value2; + + // New bytes available to process? + if (Serial1.available() > 0) { + //Serial.print("B:"); + //Serial.println(Serial1_available()); + // We rotate the Buffer (we could implement a ring buffer in future) + for (i = 7; i > 0; i--) { + UDPBuffer[i] = UDPBuffer[i - 1]; + } + UDPBuffer[0] = Serial1.read(); + Serial.print(UDPBuffer[0]); +#ifdef OSCDEBUG3 + Serial.print(UDPBuffer[0]); +#endif + // We look for an OSC message start like /x/ + if ((UDPBuffer[0] == '/') && (UDPBuffer[2] == '/') && ((UDPBuffer[1] == '1') || (UDPBuffer[1] == '2'))) { + if (OSCreadStatus == 0) { + OSCpage = UDPBuffer[1] - '0'; // Convert page to int + OSCreadStatus = 1; + OSCtouchMessage = 0; + //Serial.print("$"); +#ifdef OSCDEBUG3 + Serial.println(); +#endif + } + else { + Serial.println("!ERR:osc"); + OSCreadStatus = 1; + } + return; + } else if (OSCreadStatus == 1) { // looking for the message type + // Fadder /1/fader1 ,f xxxx + if ((UDPBuffer[3] == 'd') && (UDPBuffer[2] == 'e') && (UDPBuffer[1] == 'r')) { + OSCreadStatus = 2; // Message type detected + OSCreadCounter = 11; // Bytes to read the parameter + OSCreadNumParams = 1; // 1 parameters + OSCcommandType = UDPBuffer[0] - '0'; +#ifdef OSCDEBUG2 + Serial.print("$FAD1"); + Serial.print(OSCcommandType); + Serial.print("$"); +#endif + return; + } // end fadder + // MOVE message + if ((UDPBuffer[3] == 'o') && (UDPBuffer[2] == 'v') && (UDPBuffer[1] == 'e')) { + OSCreadStatus = 2; // Message type detected + OSCreadCounter = 8; // Bytes to read the parameters + OSCreadNumParams = 3; // 3 parameters + OSCcommandType = 40; +#ifdef OSCDEBUG2 + Serial.print("$MOVE:"); +#endif + return; + } // End MOVE message + // XY message + if ((UDPBuffer[2] == 'x') && (UDPBuffer[1] == 'y')) { + OSCreadStatus = 2; // Message type detected + OSCreadCounter = 14; // Bytes to read the parameters + OSCreadNumParams = 2; // 2 parameters + OSCcommandType = 10 + (UDPBuffer[0] - '0'); + return; + } // End XY message + // Push message + if ((UDPBuffer[3] == 'u') && (UDPBuffer[2] == 's') && (UDPBuffer[1] == 'h')) { + OSCreadStatus = 2; // Message type detected + OSCreadCounter = 10; // Bytes to read the parameter + OSCreadNumParams = 1; // 1 parameters + OSCcommandType = 20 + (UDPBuffer[0] - '1'); + //Serial.println(commandType); +#ifdef OSCDEBUG2 + Serial.print("$P"): + Serial.print(UDPBuffer[0] - '1'); + Serial.print(":"); +#endif + return; + } // end push + // Toggle message + if ((UDPBuffer[3] == 'g') && (UDPBuffer[2] == 'l') && (UDPBuffer[1] == 'e')) { + OSCreadStatus = 2; // Message type detected + OSCreadCounter = 10; // Bytes to read the parameter + OSCreadNumParams = 1; // 1 parameters + OSCcommandType = 30 + (UDPBuffer[0] - '1'); + //Serial.println(commandType); +#ifdef OSCDEBUG2 + Serial.print("$T"): + Serial.print(UDPBuffer[0] - '1'); + Serial.print(":"); +#endif + return; + } // end toggle + } else if (OSCreadStatus == 2) { + if ((UDPBuffer[1] == '/') && (UDPBuffer[0] == 'z')) { // Touch up message? (/z) [only on page1] + if ((OSCpage == 1) && (OSCcommandType <= 2)) { // Touchup message only on Fadder1 and Fadder2 + OSCtouchMessage = 1; + } + else { + OSCtouchMessage = 0; + OSCreadStatus = 0; //Finish + } + } // Touch message(/z) + OSCreadCounter--; // Reading counter until we reach the Parameter position + if (OSCreadCounter <= 0) { + OSCreadStatus = 0; + OSCnewMessage = 1; + //Serial.println(value); + switch (OSCcommandType) { + case 1: + value = OSC_extractParamFloat(0); + OSCfader[0] = value; + if ((OSCtouchMessage) && (value == 0)) { + OSCfader[0] = 0.5; + //Serial.println("TOUCH_X"); + OSC_MsgSend("/1/fader1\0\0\0,f\0\0\0\0\0\0", 20, 0.5); + } +#ifdef OSCDEBUG + Serial.print("$F1:"); + Serial.println(OSCfadder[0]); +#endif + break; + case 2: + value = OSC_extractParamFloat(0); + OSCfader[1] = value; + if ((OSCtouchMessage) && (value == 0)) { + OSCfader[1] = 0.5; + //Serial.println("TOUCH_Y"); + OSC_MsgSend("/1/fader2\0\0\0,f\0\0\0\0\0\0", 20, 0.5); + } +#ifdef OSCDEBUG + Serial.print("$F2:"); + Serial.println(OSCfadder[1]); +#endif + break; + case 3: + OSCfader[2] = OSC_extractParamFloat(0); +#ifdef OSCDEBUG + Serial.print("$F3:"); + Serial.println(OSCfadder[2]); +#endif + break; + case 4: + OSCfader[3] = OSC_extractParamFloat(0); +#ifdef OSCDEBUG + Serial.print("$F4:"); + Serial.println(OSCfadder[3]); +#endif + break; + case 11: + OSCxy1_x = OSC_extractParamFloat(0); + OSCxy1_y = OSC_extractParamFloat(4); +#ifdef OSCDEBUG + Serial.print("$XY1:"); + Serial.print(OSCxy1_x); + Serial.print(","); + Serial.println(OSCxy1_y); +#endif + break; + case 12: + OSCxy2_x = OSC_extractParamFloat(0); + OSCxy2_y = OSC_extractParamFloat(4); +#ifdef OSCDEBUG + Serial.print("$XY2:"); + Serial.print(OSCxy2_x); + Serial.print(","); + Serial.println(OSCxy2_y); +#endif + break; + case 40: + // MOVE + OSCmove_mode = 1; + OSCmove_speed = OSC_extractParamInt(4); + OSCmove_steps1 = OSC_extractParamInt(2); + OSCmove_steps2 = OSC_extractParamInt(0); +#ifdef OSCDEBUG + Serial.print("$MOVE:"); + Serial.print(OSCmove_speed); + Serial.print(","); + Serial.print(OSCmove_steps1); + Serial.print(","); + Serial.println(OSCmove_steps2); +#endif + break; + + default: + // Push y toggle + value = OSC_extractParamFloat(0); + if ((OSCcommandType >= 20) && (OSCcommandType < 25)) + { + if (value == 0) + OSCpush[OSCcommandType - 20] = 0; + else + OSCpush[OSCcommandType - 20] = 1; + } + if ((OSCcommandType >= 30) && (OSCcommandType < 35)) + { + if (value == 0) + OSCtoggle[OSCcommandType - 30] = 0; + else + OSCtoggle[OSCcommandType - 30] = 1; + } + break; + } // switch + } // if (OSCRead_counter<=0) + } // if (OSCread_status==2) + } // end Serial.available() +} + diff --git a/Arduino/BROBOT_EVO2/Servos.ino b/Arduino/BROBOT_EVO2/Servos.ino new file mode 100644 index 0000000..a12a145 --- /dev/null +++ b/Arduino/BROBOT_EVO2/Servos.ino @@ -0,0 +1,87 @@ +// BROBOT EVO 2 by JJROBOTS +// SELF BALANCE ARDUINO ROBOT WITH STEPPER MOTORS +// License: GPL v2 +// Servo and aux functions + +//#include "Arduino.h" + +// Default servo definitions +#define SERVO1_AUX_NEUTRO 1500 // Servo neutral position +#define SERVO1_MIN_PULSEWIDTH 700 +#define SERVO1_MAX_PULSEWIDTH 2300 +#define SERVO2_AUX_NEUTRO 1500 // Servo neutral position +#define SERVO2_MIN_PULSEWIDTH 700 +#define SERVO2_MAX_PULSEWIDTH 2300 + + +#define BATT_VOLT_FACTOR 8 + +int battery; + +// Init servo on T4 timer. Output OC4B (Leonardo Pin10) +// We configure the Timer4 for 11 bits PWM (enhacend precision) and 16.3ms period (OK for most servos) +// Resolution: 8us per step (this is OK for servos, around 175 steps for typical servo) +void BROBOT_initServo() +{ +int temp; + + // Initialize Timer4 as Fast PWM + TCCR4A = (1< 11 bits + + temp = 1500>>3; + TC4H = temp >> 8; + OCR4B = temp & 0xff; + + // Reset timer + TC4H = 0; + TCNT4 = 0; + + // Set TOP to 1023 (10 bit timer) + TC4H = 3; + OCR4C = 0xFF; + + // OC4A = PC7 (Pin13) OC4B = PB6 (Pin10) OC4D = PD7 (Pin6) + // Set pins as outputs + DDRB |= (1 << 6); // OC4B = PB6 (Pin10 on Leonardo board) + DDRC |= (1 << 7); // OC4A = PC7 (Pin13 on Leonardo board) + DDRD |= (1 << 7); // OC4D = PD7 (Pin6 on Leonardo board) + + //Enable OC4A and OC4B and OCR4D output + TCCR4A |= (1<>3; // Check max values and Resolution: 8us + // 11 bits => 3 MSB bits on TC4H, LSB bits on OCR4B + TC4H = pwm>>8; + OCR4B = pwm & 0xFF; +} + +void BROBOT_moveServo2(int pwm) +{ + pwm = constrain(pwm,SERVO2_MIN_PULSEWIDTH,SERVO2_MAX_PULSEWIDTH)>>3; // Check max values and Resolution: 8us + // 11 bits => 3 MSB bits on TC4H, LSB bits on OCR4B + TC4H = pwm>>8; + OCR4A = pwm & 0xFF; // Old 2.0 boards servo2 output + OCR4D = pwm & 0xFF; // New 2.1 boards servo2 output +} + +// output : Battery voltage*10 (aprox) and noise filtered +int BROBOT_readBattery(bool first_time) +{ + if (first_time) + battery = analogRead(5)/BATT_VOLT_FACTOR; + else + battery = (battery*9 + (analogRead(5)/BATT_VOLT_FACTOR))/10; + return battery; +} + + diff --git a/Hardware/electronics/brobot19.sch b/Hardware/electronics/brobot19.sch new file mode 100644 index 0000000..efc3462 --- /dev/null +++ b/Hardware/electronics/brobot19.sch @@ -0,0 +1,6404 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<h3>SparkFun Electronics' preferred foot prints</h3> +In this library you'll find boards and modules: Arduino footprints, breadboards, non-RF modules, etc.<br><br> +We've spent an enormous amount of time creating and checking these footprints and parts, but it is the end user's responsibility to ensure correctness and suitablity for a given componet or application. If you enjoy using this library, please buy one of our products at www.sparkfun.com. +<br><br> +<b>Licensing:</b> Creative Commons ShareAlike 4.0 International - https://creativecommons.org/licenses/by-sa/4.0/ +<br><br> +You are welcome to use this library for commercial purposes. For attribution, we ask that when you begin to sell your device using our footprint, you email us with a link to the product being sold. We want bragging rights that we helped (in a very small part) to create your 8th world wonder. We would like the opportunity to feature your device on our homepage. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +GND +GND ++5V +RST +VIN ++3.3V +0 +1 +2 +3 +4 +5 +Analog In +GND +13 +12 +11 +AREF +10 +9 +8 +7 +6 +5 +4 +3 +2 +TX +RX + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +GND +GND ++5V +Reset +Vin ++3.3V +0 +1 +2 +3 +4 +5 +Analog In +GND +13 +12 +11 +Aref +10 +9 +8 +7 +6 +5 +4 +3 +2 +TX +RX +PWM +PWM +PWM +PWM +PWM +PWM + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +GND +5V +RST +VIN +3V3 +0 +1 +2 +3 +4 +5 +Analog In +GND +13 +12 +11 +AREF +10 +9 +8 +7 +6 +5 +4 +3 +2 +TX +RX +GND + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +GND +GND ++5V +Reset +Vin ++3.3V +0 +1 +2 +3 +4 +5 +Analog In +GND +13 +12 +11 +Aref +10 +9 +8 +7 +6 +5 +4 +3 +2 +TX +RX + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +GND +GND +5V +RST +VIN +3.3V +0 +1 +2 +3 +4 +5 +Analog In +GND +13 +12 +11 +AREF +10 +9 +8 +7 +6 +5 +4 +3 +2 +TX +RX + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +GND +5V +RST +VIN +3V3 +0 +1 +2 +3 +4 +5 +Analog In +GND +13 +12 +11 +AREF +10 +9 +8 +7 +6 +5 +4 +3 +2 +TX +RX +GND + + + + + + + + +>Name +>Value + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Arduino shield footprint + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>Pin Header Connectors</b><p> +<author>Created by librarian@cadsoft.de</author> + + +<b>PIN HEADER</b> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + +<b>PIN HEADER</b> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + +<b>PIN HEADER</b> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>Burr-Brown Components</b><p> +<author>Created by librarian@cadsoft.de</author> + + +<b>Smal Outline Transistor</b> + + + + + + + + +>NAME +>VALUE + + + + + + +<b>DPAC</b> + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + +>NAME +>VALUE + + + + + + + +<b>800mA and 1A Low Dropout (LDO) Positive Regulator</b><p> +1.8V, 2.5V, 2.85V, 3.3V, 5V, and Adj + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<h3>SparkFun Electronics' preferred foot prints</h3> +In this library you'll find resistors, capacitors, inductors, test points, jumper pads, etc.<br><br> +We've spent an enormous amount of time creating and checking these footprints and parts, but it is the end user's responsibility to ensure correctness and suitablity for a given componet or application. If you enjoy using this library, please buy one of our products at www.sparkfun.com. +<br><br> +<b>Licensing:</b> Creative Commons ShareAlike 4.0 International - https://creativecommons.org/licenses/by-sa/4.0/ +<br><br> +You are welcome to use this library for commercial purposes. For attribution, we ask that when you begin to sell your device using our footprint, you email us with a link to the product being sold. We want bragging rights that we helped (in a very small part) to create your 8th world wonder. We would like the opportunity to feature your device on our homepage. + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + +>Value +>Name + + + + + + +>Name +>Value + + + + + + + + + + + + +>Name +>Value + + +<b>Panasonic Aluminium Electrolytic Capacitor VS-Serie Package G</b> + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + +<b>Panasonic Aluminium Electrolytic Capacitor VS-Serie Package E</b> + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + +<b>Panasonic Aluminium Electrolytic Capacitor VS-Serie Package E</b> + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + +>Value +>Name + + + + + + +>Value +>Name + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + +Type J2 package for SMD supercap PRT-10317 (p# EEC-EN0F204J2) + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<h3>EIA3528-KIT</h3> +<b>Warning:</b> This is the KIT version of this package. This package has longer pads to make hand soldering easier.<br> + + + + + + + + + + + +>NAME +>VALUE + + +<h3>EIA3216-KIT</h3> +<b>Warning:</b> This is the KIT version of this package. This package has longer pads to make hand soldering easier.<br> + + + + + + + + + + + +>NAME +>VALUE + + + + + +>Name +>Value + + + + + + + + + +>Name +>Value + + + + + + +>NAME +>VALUE + + + + + + + + +>Name +>Value + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + +>NAME +>VALUE + + + + + +<b>CAPACITOR</b><p> +chip + + + + + + + + + +>NAME +>VALUE + + + + + + + + +>Name +>Value + + + + + + + + + + + + +>Name +>Value + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + +>NAME +>VALUE + + + + + +CTZ3 Series land pattern for variable capacitor - CTZ3E-50C-W1-PF + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<h3>CAP-PTH-SMALL-KIT</h3> +Commonly used for small ceramic capacitors. Like our 0.1uF (http://www.sparkfun.com/products/8375) or 22pF caps (http://www.sparkfun.com/products/8571).<br> +<br> +<b>Warning:</b> This is the KIT version of this package. This package has a smaller diameter top stop mask, which doesn't cover the diameter of the pad. This means only the bottom side of the pads' copper will be exposed. You'll only be able to solder to the bottom side. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +This is the "EZ" version of the .1" spaced ceramic thru-hole cap.<br> +It has reduced top mask to make it harder to put the component on the wrong side of the board. + + + + + + + +>Name +>Value + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + +>NAME +>VALUE + + + + + + + + +<b>Capacitor Polarized</b> +These are standard SMD and PTH capacitors. Normally 10uF, 47uF, and 100uF in electrolytic and tantalum varieties. Always verify the external diameter of the through hole cap, it varies with capacity, voltage, and manufacturer. The EIA devices should be standard. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>Capacitor</b> +Standard 0603 ceramic capacitor, and 0.1" leaded capacitor. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<h3>SparkFun Electronics' preferred foot prints</h3> +In this library you'll find non-functional items- supply symbols, logos, notations, frame blocks, etc.<br><br> +We've spent an enormous amount of time creating and checking these footprints and parts, but it is the end user's responsibility to ensure correctness and suitablity for a given componet or application. If you enjoy using this library, please buy one of our products at www.sparkfun.com. +<br><br> +<b>Licensing:</b> Creative Commons ShareAlike 4.0 International - https://creativecommons.org/licenses/by-sa/4.0/ +<br><br> +You are welcome to use this library for commercial purposes. For attribution, we ask that when you begin to sell your device using our footprint, you email us with a link to the product being sold. We want bragging rights that we helped (in a very small part) to create your 8th world wonder. We would like the opportunity to feature your device on our homepage. + + + + + +>VALUE + + + + + +>VALUE + + + + + +>VALUE + + + + + +>VALUE + + + + + +<b>SUPPLY SYMBOL</b> + + + + + + + + + + + + +<b>SUPPLY SYMBOL</b> + + + + + + + + + + + + +Vin supply symbol + + + + + + + + + + + + + + + + + + + + + + + + + + +<h3>SparkFun Electronics' preferred foot prints</h3> +In this library you'll find resistors, capacitors, inductors, test points, jumper pads, etc.<br><br> +We've spent an enormous amount of time creating and checking these footprints and parts, but it is the end user's responsibility to ensure correctness and suitablity for a given componet or application. If you enjoy using this library, please buy one of our products at www.sparkfun.com. +<br><br> +<b>Licensing:</b> Creative Commons ShareAlike 4.0 International - https://creativecommons.org/licenses/by-sa/4.0/ +<br><br> +You are welcome to use this library for commercial purposes. For attribution, we ask that when you begin to sell your device using our footprint, you email us with a link to the product being sold. We want bragging rights that we helped (in a very small part) to create your 8th world wonder. We would like the opportunity to feature your device on our homepage. + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + +>Name +>Value + + +<b>RESISTOR</b><p> +chip + + + + + + + + + + +>NAME +>VALUE + + + + + + + + +>NAME +>VALUE + + + + + + + + + + +>NAME +>VALUE + + + + + + +1/6W Thru-hole Resistor - *UNPROVEN* + + + + + + +>NAME +>VALUE + + + + + + +>NAME +>VALUE + + + + +1/4W Resistor, 0.4" wide<p> + +Yageo CFR series <a href="http://www.yageo.com/pdf/yageo/Leaded-R_CFR_2008.pdf">http://www.yageo.com/pdf/yageo/Leaded-R_CFR_2008.pdf</a> + + + + + + +>Name +>Value + + +1/2W Resistor, 0.5" wide<p> + +Yageo CFR series <a href="http://www.yageo.com/pdf/yageo/Leaded-R_CFR_2008.pdf">http://www.yageo.com/pdf/yageo/Leaded-R_CFR_2008.pdf</a> + + + + + + +>Name +>Value + + +1W Resistor, 0.6" wide<p> + +Yageo CFR series <a href="http://www.yageo.com/pdf/yageo/Leaded-R_CFR_2008.pdf">http://www.yageo.com/pdf/yageo/Leaded-R_CFR_2008.pdf</a> + + + + + + +>Name +>Value + + +2W Resistor, 0.8" wide<p> + +Yageo CFR series <a href="http://www.yageo.com/pdf/yageo/Leaded-R_CFR_2008.pdf">http://www.yageo.com/pdf/yageo/Leaded-R_CFR_2008.pdf</a> + + + + + + +>Name +>Value + + +<h3>AXIAL-0.3-KIT</h3> + +Commonly used for 1/4W through-hole resistors. 0.3" pitch between holes.<br> +<br> + +<b>Warning:</b> This is the KIT version of the AXIAL-0.3 package. This package has a smaller diameter top stop mask, which doesn't cover the diameter of the pad. This means only the bottom side of the pads' copper will be exposed. You'll only be able to solder to the bottom side. + + + + + + + + + + +>Name +>Value + + + + + + + + + + + + + + + + + + + + + + + + + + +This is the "EZ" version of the standard .3" spaced resistor package.<br> +It has a reduced top mask to make it harder to install upside-down. + + + + + + + + + + +>Name +>Value + + + + + + + + + + + + +>Name +>Value + + + + + + + + + + + + + +>Name +>Value + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + +<b>Resistor</b> +Basic schematic elements and footprints for 0603, 1206, and PTH resistors. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>SMA Surface Mount Diode</b> + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + +>Name +>Value + + +<b>SOT23</b> - Reflow soldering + + + + + + + + + + + + +>NAME +>VALUE + + + + + +<b>SOT23</b> - Wave soldering + + + + + + + + + + +>NAME +>VALUE + + + + + +SOD-523 (0.8x1.2mm) + +<p>Source: http://www.rohm.com/products/databook/di/pdf/rb751s-40.pdf</p> + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + +Antenna + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ESP12 + + + + +For use by pick and place machines to calibrate the vision/machine, 1mm +<p>By microbuilder.eu</p> + + + + + + + + + + + + +<b>Diode</b> +<p> +<b>SMADIODE</b> - SMA Surface Mount Package +<ul> +<li>20V 1A Schottky Diode Digikey: 641-1014-6-ND</li> +</ul> +<b>DO-1N4148</b> - Through Hole Small Current Diode<br> +<b>SOD-123</b> +<ul> +<li>20V 1 A (.5mV Vf) Schottky Diode - Digikey: MBRX120TPMSCT-ND</li> +</ul> +<b>SOD-323</b> +<ul> +<li>10V 570mA (.38mV Vf, 3ns) Schottky Diode - Digikey: ZLLS410CT-ND</li> +</ul> +<b>SOD-523</b> +<ul> +<li>30V 30mA Schottky Diode (RB751S-40TE61) - Digikey: RB751S-40TE61CT-ND</li> +</ul> +<b>SOT23-R/W</b> - SOT23 Package (R = Solder Paste/Reflow Ovens, W = Hand-Soldering) +<ul> +<li>BAT54Film 40V 300mA - Digikey: 497-7162-1-ND</li> +</ul> +</p> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<h3>SparkFun Electronics' preferred foot prints</h3> +In this library you'll find connectors and sockets- basically anything that can be plugged into or onto.<br><br> +We've spent an enormous amount of time creating and checking these footprints and parts, but it is the end user's responsibility to ensure correctness and suitablity for a given componet or application. If you enjoy using this library, please buy one of our products at www.sparkfun.com. +<br><br> +<b>Licensing:</b> Creative Commons ShareAlike 4.0 International - https://creativecommons.org/licenses/by-sa/4.0/ +<br><br> +You are welcome to use this library for commercial purposes. For attribution, we ask that when you begin to sell your device using our footprint, you email us with a link to the product being sold. We want bragging rights that we helped (in a very small part) to create your 8th world wonder. We would like the opportunity to feature your device on our homepage. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + +This footprint was designed to help hold the alignment of a through-hole component (i.e. 6-pin header) while soldering it into place. +You may notice that each hole has been shifted either up or down by 0.005 of an inch from it's more standard position (which is a perfectly straight line). +This slight alteration caused the pins (the squares in the middle) to touch the edges of the holes. Because they are alternating, it causes a "brace" +to hold the component in place. 0.005 has proven to be the perfect amount of "off-center" position when using our standard breakaway headers. +Although looks a little odd when you look at the bare footprint, once you have a header in there, the alteration is very hard to notice. Also, +if you push a header all the way into place, it is covered up entirely on the bottom side. This idea of altering the position of holes to aid alignment +will be further integrated into the Sparkfun Library for other footprints. It can help hold any component with 3 or more connection pins. + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + +>Name +>Value ++ +- +S +S + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>Name +>Value ++ +- +Y +B + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +2mm SMD side-entry connector. tDocu layer indicates the actual physical plastic housing. +/- indicate SparkFun standard batteries and wiring. + + + + + + + + + + + + + +>Name +>Value ++ +- + + + + + + + + + + + + + + + + + + + + + + + + + +>Name +>Value + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + +This footprint was designed to help hold the alignment of a through-hole component (i.e. 6-pin header) while soldering it into place. +You may notice that each hole has been shifted either up or down by 0.005 of an inch from it's more standard position (which is a perfectly straight line). +This slight alteration caused the pins (the squares in the middle) to touch the edges of the holes. Because they are alternating, it causes a "brace" +to hold the component in place. 0.005 has proven to be the perfect amount of "off-center" position when using our standard breakaway headers. +Although looks a little odd when you look at the bare footprint, once you have a header in there, the alteration is very hard to notice. Also, +if you push a header all the way into place, it is covered up entirely on the bottom side. This idea of altering the position of holes to aid alignment +will be further integrated into the Sparkfun Library for other footprints. It can help hold any component with 3 or more connection pins. + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + +>Name +>Value ++ +- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + +>Name +>Value ++ +- + + +<H3>JST-2-PTH-KIT</h3> +2-Pin JST, through-hole connector<br> +<br> +<b>Warning:</b> This is the KIT version of this package. This package has a smaller diameter top stop mask, which doesn't cover the diameter of the pad. This means only the bottom side of the pads' copper will be exposed. You'll only be able to solder to the bottom side. + + + + + + + + + +>Name +>Value ++ +- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>Name +>Value ++ +- + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + +This footprint was designed to help hold the alignment of a through-hole component (i.e. 6-pin header) while soldering it into place. +You may notice that each hole has been shifted either up or down by 0.005 of an inch from it's more standard position (which is a perfectly straight line). +This slight alteration caused the pins (the squares in the middle) to touch the edges of the holes. Because they are alternating, it causes a "brace" +to hold the component in place. 0.005 has proven to be the perfect amount of "off-center" position when using our standard breakaway headers. +Although looks a little odd when you look at the bare footprint, once you have a header in there, the alteration is very hard to notice. Also, +if you push a header all the way into place, it is covered up entirely on the bottom side. This idea of altering the position of holes to aid alignment +will be further integrated into the Sparkfun Library for other footprints. It can help hold any component with 3 or more connection pins. + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + +>NAME +>VALUE + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + +>Name +>Value ++ +- +S + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + +>Name +>Value + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + +>Value +>Name + + + + + + + + + + + + + + + + + + + + +<h3>SMD 3-Pin Male Right-Angle Header w/ Alignment posts</h3> + +Matches 4UCONN part # 11026<br> +<a href="http://www.4uconnector.com/online/object/4udrawing/11026.pdf">http://www.4uconnector.com/online/object/4udrawing/11026.pdf</a> + + + + + + + + + + + + + + + + + + + + +This 3-pin connector mates with the JST cable sold on SparkFun. + + + + + + + + + + + +>Name +>Value ++ +- +S + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>VALUE +>NAME + + + + + + + + + + + + +>VALUE +>NAME + + + + + + + + + + + +>VALUE +>NAME + + + + + + + +<b>Header 4</b> +Standard 4-pin 0.1" header. Use with straight break away headers (SKU : PRT-00116), right angle break away headers (PRT-00553), swiss pins (PRT-00743), machine pins (PRT-00117), and female headers (PRT-00115). Molex polarized connector foot print use with SKU : PRT-08231 with associated crimp pins and housings. 1MM SMD Version SKU: PRT-10208 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Standard 2-pin 0.1" header. Use with <br> +- straight break away headers ( PRT-00116)<br> +- right angle break away headers (PRT-00553)<br> +- swiss pins (PRT-00743)<br> +- machine pins (PRT-00117)<br> +- female headers (PRT-00115)<br><br> + + Molex polarized connector foot print use with: PRT-08233 with associated crimp pins and housings.<br><br> + +2.54_SCREWTERM for use with PRT-10571.<br><br> + +3.5mm Screw Terminal footprints for PRT-08084<br><br> + +5mm Screw Terminal footprints for use with PRT-08433 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>Header 3</b> +Standard 3-pin 0.1" header. Use with straight break away headers (SKU : PRT-00116), right angle break away headers (PRT-00553), swiss pins (PRT-00743), machine pins (PRT-00117), and female headers (PRT-00115). Molex polarized connector foot print use with SKU : PRT-08232 with associated crimp pins and housings. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>Linear Devices</b><p> +Operational amplifiers, comparators, voltage regulators, ADCs, DACs, etc.<p> +<author>Created by librarian@cadsoft.de</author> + + +<b>TO-92</b> + + + + + + + + + + + + +>NAME +>VALUE + + +<b>TO-220</b> + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + +<b>Metal Can Package</b> + + + + + + + + +>NAME +>VALUE + + +<b>SMALL OUTLINE TRANSISTOR</b><p> +TS-003 + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + +<b>TO 200 vertical</b> + + + + + + + + + +>NAME +>VALUE +1 +2 +3 + + + + + + + + + + + + + + + + +>NAME +>VALUE +GND + + + + + + + +Positive <b>VOLTAGE REGULATOR</b><p> +Source:<br> +http://cache.national.com/ds/LM/LM78L05.pdf<br> +http://www.fairchildsemi.com/ds/LM/LM7805.pdf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>Molex Connectors</b><p> +<author>Created by librarian@cadsoft.de</author> + + +<b>4 Pin - 2mm Dual Row Single Wafer, Vertical T/H HDR</b><p> +Source: http://www.molex.com/pdm_docs/sd/877580616_sd.pdf + + + + + + + + + + + + +1 +>NAME +>VALUE + + + + + + + + + +>NAME +>VALUE + + + + +>NAME + + + + + +<b>4 Pin - 2mm Dual Row Single Wafer, Vertical T/H HDR</b><p> +Source: http://www.molex.com/pdm_docs/sd/877580616_sd.pdf + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>Pin Header Connectors</b><p> +<a href="www.mpe-connector.de">Menufacturer</a><p> +<author>Created by librarian@cadsoft.de</author> + + +<b>2 Pin - 2mm Dual Row</b><p> +Source: www.mpe-connector.de / garry_shortform_2012.pdf + + + + + + + + + + +1 +>NAME +>VALUE + + + + + + + +>NAME +>VALUE + + + + + +<b>2 Pin - 2mm Dual Row</b><p> +Source: www.mpe-connector.de / garry_shortform_2012.pdf + + + + + + + + + + + + + + + + + + + +<h3>SparkFun Electronics' preferred foot prints</h3> +In this library you'll find anything that moves- switches, relays, buttons, potentiometers. Also, anything that goes on a board but isn't electrical in nature- screws, standoffs, etc.<br><br> +We've spent an enormous amount of time creating and checking these footprints and parts, but it is the end user's responsibility to ensure correctness and suitablity for a given componet or application. If you enjoy using this library, please buy one of our products at www.sparkfun.com. +<br><br> +<b>Licensing:</b> Creative Commons ShareAlike 4.0 International - https://creativecommons.org/licenses/by-sa/4.0/ +<br><br> +You are welcome to use this library for commercial purposes. For attribution, we ask that when you begin to sell your device using our footprint, you email us with a link to the product being sold. We want bragging rights that we helped (in a very small part) to create your 8th world wonder. We would like the opportunity to feature your device on our homepage. + + +<b>OMRON SWITCH</b> + + + + + + + + + + + + + + + + + + + + + + + + +>NAME + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>Value + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + +<b>Momentary Switch</b><br> +Button commonly used for reset or general input.<br> +Spark Fun Electronics SKU : COM-00097<br> +SMT- SWCH-08247 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +SERVO 5V +B-ROBOT Project Arduino shield (for Leonardo board) v2.2 +Designed by JJROBOTS.COM (Jose Julio & Juan Pedro) +Realeased under the Creative Commons attribution share-alike 3.0 license + + + + +ESP External reset +ESP External Flash +SERVO1 +SERVO2 +MS3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +