Sojourner F17: Custom Commands & Telemetry
/in Mini Pathfinder, Sojourner Generation #2/by Daniel YeldellSojourner F17 – Preliminary and Final 3D Print Time (Updated)
/in Mini Pathfinder, Sojourner Generation #2/by Daniel YeldellSojourner F17: Solar Panel and Phone Mount Integration
/in Mini Pathfinder, Sojourner Generation #2/by Daniel YeldellEE346/EE444 Software Translation to EE400D
/in Mod Wheels Generation #1/by Lucas GutierrezBy: Matt Shellhammer (Electronics & Control Engineer for ModWheels) & Mark Huffman (Project Manager for Goliath)
Approved by: Lucas Gutierrez (Project Manager for ModWheels)
Table of Contents
Introduction
This software is simply an outline and requires modification for each project. The software translation is to ease the implementation of your projects specific software such as turning, detection, line following, etc. Some subroutines are completed (e.g. the virtual instructions: turnInMaze, stepInMaze, and roomInMaze) and others are left empty for each project to develop their specific robot implementations.
Software
400D_Software_Translation.ino (MAIN SETUP & LOOP)
////////////////////////////////////////////////////////////////
// Name : 400D Software Translation //
// Author : Matt Shellhammer & Mark Huffman //
// Date : 29 November, 2017 //
// Version : 1.0 //
////////////////////////////////////////////////////////////////
#define __PROG_TYPES_COMPAT__ // __PROG_TYPES_COMPAT__
#include <avr/pgmspace.h>
#include <Robot3DoTBoard.h>
#include <EEPROM.h>
#include <Wire.h>
#include <Servo.h>
#include "maze.h"
Robot3DoTBoard Robot3DoT; // define a 3DoT Robot instance
Motor mA; // define a motor A instance
Motor mB; // define a motor B instance
// Define motor driver pins
#define AIN1 5
#define BIN1 19
#define AIN2 10
#define BIN2 20
#define PWMA 9
#define PWMB 6
#define STBY A0
// Define encoder pins for specific 400D project
#define encoderL A3
#define encoderR A4
void setup() {
Serial.begin(9600);
Robot3DoT.begin();
// Define motor driver pins
mA.begin(AIN1,AIN2,PWMA);
mB.begin(BIN1,BIN2,PWMB);
// Make Encoder pins inputs
pinMode(encoderL,INPUT);
pinMode(encoderR,INPUT);
delay(5000);
}
void loop() {
static uint8_t type;
static myRobot_t robot_inst; // create an instance of myRobot_t called robot_inst
static sensors_t sensors_inst; // create an instance of sensors_t called sensors_inst
static motors_t motors_inst; // create an instance of motors_t called motors_inst
static PID_t PID_inst; // create an instance of PID_t called PID_inst
sensors_inst = readSensors(sensors_inst); // Read sensor values
PID_inst = PIDcalc(sensors_inst, PID_inst); // Calculate PID value
motors_inst = errorCorrection(PID_inst, motors_inst); // Correct for error with motors
forward(motors_inst); // send new speed to motors to move forward
// Check if at an intersection (NOTE: MUST BE MODIFIED FOR EACH PROJECT, THIS IS JUST HOW I DID IT)
float sensorAvg = (sensors_inst.IR0 + sensors_inst.IR1 - sensors_inst.IR2)/3.0;
if (sensorAvg > 0.125){
robot_inst = enterRoom(robot_inst);
type = roomType(robot_inst);
robot_inst.dir = whichWay(type, robot_inst);
}
}
maze.h (Structure, array, and variable definitions)
// PID constants (NOTE: MUST BE MODIFIED FOR EACH PROJECT, THIS IS JUST HOW I DID IT)
const uint8_t Kp = 100;
const float Ki = 0.1;
const uint8_t Kd = 50;
const uint8_t base_speed = 60;
struct coord_t{
uint8_t row = 0x13; // Robot is initially outside of the maze
uint8_t col = 0x00; // Robot is initially outside of the maze
};
struct myRobot_t{
uint8_t dir = 0x03; // Robot is initially facing north
uint8_t turn = 0x00; // First action is no turn
coord_t maze;
uint8_t room = 0x00; // Initial room is empty
uint8_t bees = 0x00; // No bees present
};
struct sensors_t{
float IR0; // Left IR sensor (normalized)
float IR1; // Middle IR sensor (normalized)
float IR2; // Right IR sensor (normalized)
};
struct motors_t{
int16_t leftSpeed = 60; // Initial motor speed: 60
int16_t rightSpeed = 60; // Initial motor speed: 60
};
// Define PID structure
struct PID_t{
float present = 0;
float set_point = 0;
float proportional = 0;
float integral = 0;
float derivative = 0;
int16_t PIDvalue = 0;
float error = 0;
float previous_error = 0;
};
const uint8_t hit_table[] PROGMEM =
{0x08, // South (dir == 0b00)
0x02, // East (dir == 0b01)
0x04, // West (dir == 0b10)
0x01}; // North (dir == 0b11)
//Compass S E W N
//dir 00 01 10 11
const uint8_t turn_table[] PROGMEM =
{0b00, 0b01, 0b10, 0b11, // 00 no turn
0b10, 0b00, 0b11, 0b01, // 01 turn right
0b01, 0b11, 0b00, 0b10, // 10 turn left
0b11, 0b10, 0b01, 0b00 // 11 turn around
};
// row col dir
const int8_t map_table[] PROGMEM =
{1 , 0, // 00
0 , 1, // 01
0 , -1, // 10
-1 , 0 // 11
};
const int maze_length = 399;
const uint8_t theMaze[] PROGMEM =
// 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14
{0x05,0x09,0x09,0x09,0x09,0x09,0x01,0x03,0x05,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x29,0x09,0x09,0x09,0x02, // 00
0x0C,0x09,0x09,0x03,0x05,0x09,0x0A,0x06,0x06,0x05,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x03,0x05,0x03,0x06, // 01
0x05,0x09,0x0B,0x06,0x06,0x05,0x09,0x0A,0x06,0x0C,0x09,0x09,0x09,0x09,0x09,0x01,0x0B,0x0C,0x0A,0x06,0x06, // 02
0x06,0x0D,0x09,0x0A,0x06,0x06,0x05,0x03,0x0C,0x09,0x09,0x03,0x05,0x09,0x09,0x0A,0x05,0x09,0x09,0x08,0x02, // 03
0x06,0x05,0x09,0x09,0x0A,0x06,0x06,0x0C,0x09,0x09,0x09,0x0A,0x0C,0x09,0x09,0x03,0x06,0x05,0x09,0x09,0x0A, // 04
0x06,0x0C,0x03,0x05,0x09,0x02,0x06,0x05,0x09,0x09,0x09,0x09,0x09,0x09,0x03,0x06,0x06,0x0C,0x03,0x05,0x03, // 05
0x06,0x05,0x0A,0x0C,0x03,0x06,0x06,0x06,0x05,0x01,0x03,0x07,0x05,0x03,0x06,0x06,0x06,0x05,0x0A,0x06,0x06, // 06
0x06,0x0C,0x09,0x03,0x0E,0x0C,0x08,0x02,0x06,0x06,0x06,0x06,0x06,0x06,0x0C,0x02,0x06,0x0C,0x09,0x02,0x06, // 07
0x06,0x05,0x0B,0x0C,0x09,0x09,0x09,0x08,0x02,0x06,0x06,0x06,0x06,0x0C,0x09,0x0A,0x04,0x09,0x0B,0x06,0x06, // 08
0x0C,0x08,0x09,0x09,0x09,0x09,0x01,0x01,0x02,0x06,0x0C,0x08,0x08,0x09,0x01,0x09,0x08,0x09,0x03,0x06,0x06, // 09
0x05,0x01,0x09,0x09,0x0B,0x07,0x06,0x04,0x02,0x0C,0x09,0x09,0x09,0x03,0x04,0x09,0x03,0x07,0x06,0x06,0x06, // 0A
0x06,0x0C,0x09,0x09,0x09,0x02,0x06,0x04,0x02,0x0D,0x09,0x09,0x09,0x0A,0x0C,0x03,0x06,0x06,0x06,0x06,0x06, // 0B
0x06,0x05,0x09,0x09,0x09,0x0A,0x06,0x0C,0x0A,0x05,0x09,0x09,0x09,0x09,0x03,0x06,0x06,0x06,0x06,0x06,0x06, // 0C
0x06,0x0C,0x09,0x09,0x09,0x03,0x04,0x09,0x09,0x08,0x0B,0x05,0x03,0x05,0x0A,0x06,0x06,0x06,0x06,0x06,0x06, // 0D
0x04,0x09,0x09,0x09,0x09,0x08,0x02,0x05,0x01,0x09,0x03,0x06,0x06,0x06,0x05,0x0A,0x0E,0x06,0x06,0x06,0x06, // 0E
0x06,0x05,0x09,0x09,0x09,0x09,0x0A,0x0E,0x06,0x07,0x06,0x06,0x06,0x06,0x06,0x05,0x09,0x0A,0x06,0x06,0x06, // 0F
0x06,0x0C,0x09,0x09,0x09,0x09,0x09,0x09,0x0A,0x06,0x06,0x06,0x06,0x0E,0x0E,0x06,0x05,0x09,0x0A,0x06,0x06, // 10
0x04,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0A,0x0C,0x0A,0x06,0x05,0x09,0x0A,0x06,0x0D,0x09,0x0A,0x06, // 11
0x04,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x08,0x08,0x09,0x09,0x08,0x09,0x09,0x09,0x0A, // 12
};
subroutines.ino
myRobot_t enterRoom(myRobot_t robot){
robot = turnInMaze(robot);
robot = stepInMaze(robot);
robot = roomInMaze(robot);
return robot;
}
// Returns updated direction based on current direction and turn value
// values returned in robot structure
myRobot_t turnInMaze(myRobot_t robot){
// index = 4*turn_val + dir_val
uint8_t index = (robot.turn << 2) + robot.dir;
robot.dir = pgm_read_byte_near(turn_table + index);
return robot;
}
// Returns updated row and column values after taking a step in current direction
// values returned in robot structure
myRobot_t stepInMaze(myRobot_t robot){
// index = 2*robot.dir
uint8_t index = (robot.dir << 1);
robot.maze.row += pgm_read_byte_near(map_table + index); // Add either -1, 0, or 1 to current row value
robot.maze.col += pgm_read_byte_near(map_table + index + 1); // Add either -1, 0, or 1 to current column value
return robot;
}
// Returns updated room and bees values using current row and column values
// values returned in robot structure
myRobot_t roomInMaze(myRobot_t robot){
// index = 21*robot.maze.row + robot.maze.col
uint16_t index = (21*robot.maze.row) + robot.maze.col;
uint8_t maze_val = pgm_read_byte_near(theMaze + index);
robot.room = maze_val & 0x0F; // clear upper nibble and store as the room value
uint8_t temp_bees = (maze_val & 0xF0) >> 4; // clear lower nibble and store as the temp bees value
robot.bees += temp_bees; // add temp_bees to curret bees value
return robot;
}
// Room Type subroutine
uint8_t roomType(myRobot_t robot){
bool leftWall = leftHit(robot); // Test if hiting left wall
bool hit = hitWall(robot); // Test if facing wall
bool rightWall = rightHit(robot); // Test if hiting right wall
uint8_t room = (uint8_t(leftWall) << 2)|(uint8_t(hit) << 1)|uint8_t(rightWall); // Convert to room type
return room;
}
// Returns true if there is a wall and false if there is no wall
bool hitWall(myRobot_t robot){
// index = dir_val
robot = roomInMaze(robot); // Determine room value
uint8_t wallVal = pgm_read_byte_near(hit_table + robot.dir); // Determine wall bit based on direction
uint8_t outVal = bool(wallVal & robot.room); // Clear all bits other than the wall robot is facing
if (outVal == 0){return false;} // If the robot is not hiting a wall outVal will equal zero
else {return true;} // and the subroutine will return false, else it returns true.
}
// Returns true if there is a wall and false if there is no wall
// on the right side of the robot
bool rightHit(myRobot_t robot){
robot.turn = 0x01; // Modify turn value to turn right
robot = turnInMaze(robot); // Call turnInMaze to turn the robot (virtually)
bool hit = hitWall(robot); // Test hit wall
return hit;
}
// Returns true if there is a wall and false if there is no wall
// on the left side of the robot
bool leftHit(myRobot_t robot){
robot.turn = 0x02; // Modify turn value to turn left
robot = turnInMaze(robot); // Call turnInMaze to turn the robot (virtually)
bool hit = hitWall(robot); // Test hit wall
return hit;
}
sensors_t readSensors(sensors_t sensors){
// Write software to read color sensors/color shield
}
// NOTE: MUST BE MODIFIED FOR EACH PROJECT, THIS IS JUST HOW I DID IT
PID_t PIDcalc(sensors_t sensors, PID_t PID){
// Calculates error
PID.present = sensors.IR0 + sensors.IR2;
PID.error = PID.present - PID.set_point;
// Calculates proportional error
PID.proportional = PID.error;
// Calculates integrated error
PID.integral += PID.error;
// Calculate change in error
PID.derivative = PID.error - PID.previous_error;
PID.previous_error = PID.error;
// Calculate compensator value
// this should be an integer from -128 to 127 which is why the casting function is used
PID.PIDvalue = int8_t(Kp*PID.proportional + Ki*PID.integral + Kd*PID.derivative);
return PID;
}
// NOTE: MUST BE MODIFIED FOR EACH PROJECT, THIS IS JUST HOW I DID IT
// errorCorrection: corrects motor speed based on PID value (limits between <50,220>)
motors_t errorCorrection(PID_t PID, motors_t motors){
motors.leftSpeed = base_speed - PID.PIDvalue;
motors.rightSpeed = base_speed + PID.PIDvalue;
// Limit the left and right motor speeds between <50,220>
if (motors.rightSpeed > 220) {motors.rightSpeed = 220;}
if (motors.leftSpeed > 220) {motors.leftSpeed = 220;}
if (motors.rightSpeed < 50) {motors.rightSpeed = 50;}
if (motors.leftSpeed < 50) {motors.leftSpeed = 50;}
return motors;
}
void readEncoders(uint16_t numCount){
// Write readEncoders for specific 400D project
}
uint8_t whichWay(MyRobot mazeBot){
// Automatically handles intersections where no decision is needed
// the rest need to be defined
// TODO: Needs recording decisions added
// TODO: Needs playback added
switch(roomType(mazeBot)){
case 0:
// 4 way Intersection
// TODO: Decision Needed!
return 0x00;
case 1:
// T-Intersection (Wall to right)
// TODO: Decision Needed!
return 0x00;
case 2:
// T-Intersection (Wall to Left)
// TODO: Decision Needed!
return 0x00;
case 3:
// Hallway Continue Forward
return 0x00;
case 4:
// T-Intersection (Wall in Front)
// TODO: Decision Needed!
return 0x00;
case 5:
// Left Turn (Turn Left)
return 0x02;
case 6:
// Right Turn (Turn Right)
return 0x01;
case 7:
// Dead End (Turn Around)
return 0x03;
}
}
}
void forward(motors_t motors){
// Write forward for specific 400D project
}
void turn_right() {
// Write turn_right for specific 400D project
}
void turn_left() {
// Write turn_left for specific 400D project
}
void turn_around() {
// Write turn_around for specific 400D project
}
void go_straight() {
digitalWrite(STBY, HIGH);
digitalWrite(AIN2, HIGH);
digitalWrite(AIN1, LOW);
digitalWrite(BIN1, LOW);
digitalWrite(BIN2, HIGH);
analogWrite(PWMA, base_speed);
analogWrite(PWMB, base_speed);
}
void stopRobot(uint16_t d) {
digitalWrite(STBY, HIGH);
digitalWrite(AIN2, HIGH);
digitalWrite(AIN1, LOW);
digitalWrite(BIN1, HIGH);
digitalWrite(BIN2, LOW);
analogWrite(PWMA, 0);
analogWrite(PWMB, 0);
delay(d);
}
Software Explanation
Structures & Variables
maze.h is where all structures, arrays and variables are defined, and they are defined as follows:
PID constants
These constants are Kp, Ki, Kd, and the motors base speed for the subroutines “PIDcalc” and “errorCorrection”.
coord_t and myRobot_t
This is where all variables are stored for the virtual instructions of the maze. These structures hold: row, column, direction, turn, room, and bees.
sensors_t, motors_t, and PID_t
sensors_t is a structure to hold values of the sensors. This can be modified for color sensors, proximity sensors, etc. motors_t is a structure for the left and right motor speeds. PID_t is a structure to hold all values for the PID calculations within the subroutine “PIDcalc”.
hit_table
This array is used in the subroutine “hitWall” to clear all bit other than the bit representing the wall that the robot is facing.
turn_table
This array is used to implement turns within “turnInMaze”.
map_table
This array is used within “stepInMaze” to modify row and column.
theMaze
This array is the virtual maze storing all room values throughout the maze.
Subroutines
subroutines.ino is where all structures, arrays and variables are defined, and they are defined as follows:
enterRoom, turnInMaze, stepInMaze, and roomInMaze
enterRoom takes the robot instance structure as a parameter and and calls turnInMaze, stepInMaze, and roomInMaze using that structure as an argument for each subroutine and then returns an updated robot instance. turnInMaze updates the direction of the robot instance based on the current direction and the turn value. stepInMaze updates row and column based on the robots direction. roomInMaze updates room and bees values using current row and column values.
roomType, hitWall, rightHit, and leftHit
roomType calls hitWall, rightHit, and leftHit to then determine the room type based on the direction of the robot. hitWall determines if the robot is hitting a wall, right and left hit determine if there is a wall on the right or left side of the robot.
PIDcalc and errorCorrection
PIDcalc uses the sensor reading to calculate a PID value which will then be used to modify the motor speeds within the errorCorrection.
whichWay
Same as in EE 346.
References
http://web.csulb.edu/~hill/ee444/Labs/
ModWheels C-clamps versus nut capture
/in Mod Wheels Generation #1/by Lucas GutierrezBy: Vanessa Enriquez (Design & Manufacturing Engineer for Goliath)
Approved by: Lucas Gutierrez (Project Manager for ModWheels)
Initial design
After printing the first design, the customer asked to introduce another way to assemble the toy and suggested nut captures. The first design uses the c-clamps, which have been successfully implemented in previous models. The model shown below was assembled by Natalie, the Modwheels manufacturing engineer.
Figure 1 – Initial design assembly
Alternate assembly
Implementing the nut capture method requires a couple of design changes to the top and bottom panels. After researching different methods, I decided on a simple solution. The simple solution is to replace the squared cutouts for the clamps with circle cutouts. This may cause stress on the rest of the part. A second more detailed solution is explained in source 1. The latter requires an increase in thickness on both panels. For the spacers modeled below, Natalie suggested using nylon material.
Figure 2 – Nut capture assembly (Solidworks)
Figure 3 – Nut capture assembly
Sources
Goliath Fall 2017 – 3DOT 4.54
/in 3DoT Goliath, Goliath Generation #3/by Mark HuffmanWhile waiting for the new 3Dot board (5.03) the 3Dot 4.54 version board is being used for development. Physically the boards are nearly the same. The only major change that affects us is the placement of headers and connectors. On the new board, there are two separate locations to connect I2C devices. So, our devices can route […]
Goliath Fall 2017 – Breadboarding
/in 3DoT Goliath, Goliath Generation #3/by Mark HuffmanAll major components have been laid out on a breadboard for testing the majority of the program work. Most importantly being the color sensors and gyro. As both provide vital functions for navigating the maze. This breadboarding has provided very useful as the previous Goliath has been used as a test platform with room for new components on top. […]
Antenna Matching
/in 3DoT Chassis/by Elizabeth NguyenWritten by Zachary de Bruyn (Electronics & Control)
Table of Contents
Purpose
The PeteBot chassis team is unique in that it is utilizing two PCBs which operate on two different MCUs; the first being the heritage 3DoT v5.03 board which uses the ATMega32U4, and the second being the SAMB11, which incorporates the ATSAMB11. One significant different between the two boards is that the SAMB11 has a transceiver module. Because the SAMB11 can operate with the incorporated Bluetooth (BLE), an antenna network was needed to be designed to utilize the BLE transceiver. Because an antenna network was needed to be constructed with minimal input from the SAMB11 reference design, many steps were required to be performed in order to ensure that the SAMB11 could operate at the 2.4-GHz BLE frequency.
Antenna Selection
The first step in the overal process of incorporated a matching network is selecting a proper antenna based on the needs of the system. To reiterate, the operating frequency of BLE is 2.4-GHz. Along with frequency requirements, there are also size requirements. Our antenna therefore was required to operate at the BLE frequency, to be small enough to fit on a PCB, and to operate the PeteBot chassis. These requirements alone narrowed the possibilites of two types of antennas: PCB or chip antennas. With the PCB antennas, one antenna that looks promising is the meandered inverted-F antenna (MIFA). The chip antenna resembles a 0805 resistor or inductor. The two antennas are shown below:
Analyzing both types and data sheets of antennas, we discover that both antennas have an isotropic radiation pattern, meaning that the frequency of the antenna can be picked up equally from almost every direction. This is ideal for our applications due to the fact that the PeteBot will be required to operate via RC mode by an operated. A few other important antenna parameters are: return loss, gain, and bandwidth. Return loss is essentially how much of the power being transmitted is reflected due to the mismatch of the antenna’s imepdances. The standard for impedances is usually 50-Ohms. A return loss greater or equal to 10-dB is considered ideal for operation [1]. Referring to the following equaltion for return loss:
At a return loss of 10-dB which translates to 90% of power transmittered going into the antenna, return loss of 20-dB translates to 99%. The gain is a measure of ow strong the radiation field is compared to the ideal omnidirectional antenna. For isotropic antennas, like that being applied to the PeteBot, gain is measured as dBi. The “i” simply indicates that the gain is measured frerence to an istropic antenna. While the MIFA antenna has a gain of about 5-dB depending on the plane of radation, the chip antenna has a peak gain of 0.5-dBi. The bandwidth requirements for the antennas requires that the BLE frequency is capable of interception, which was 2.4-GHz. The chip antenna has a frequency range of 2.4- to 2.5-GHz, which translates to a bandwidth of 100-MHz. The MIFA antenna operates a a comparable frequency range, and therefore has an equivalent bandwidth.
With comparable operational characteristics, an antenna selection for our purposes was based upon flexibility, in which the antenna can be used in a variety of configurations for the SAMB11 board. In the case of the PeteBot SAMB11 PCB, the chip antenna is the best candidate.
Matching Network
The purpose of an antenna matching network is to allow the most power to be delivered to the load. The load in the case of transcievers, like the SAMB11, is dependent on whether the antenna is transmitting or receiving. If the antenna is transmitting, then the antenna is the load, whicl the SoC SAMB11 is the load if the system is receiving. It is common practice to design a load with 50-Ohm impedences for RF traces [1]. As a review, the term impedance is mathematically defined as the magnitude of resistance and reactance. It is typically denoted by the letter “Z.”
In Equations (2) and (3), R denotes resistance, and X for reactance. Both values are measured in Ohms.
Now that impedance is defined and the typical characteristic impedance is defined as 50-Ohms, this information can be used in collaboration with the helpful tool called a Smith Chart.
Smith Chart
It is a graphicaly tool used to help plot complex impedances and used to define a matching network. It is also helpful in determining many important RF parameters, including VSWR, return loss, reflection coefficient, and transmission coefficients. Using this chart can design a matching network.
There are a lot of reference towards using Smith charts on YouTube that will explain how to find the difference parameters.
The best usage of the Smith chart is to be able to measure the input impedances going into a load, where the input impedance is defined as Z_in. Character impedance is Z_0 and the load impedance is Z_L.
As an example, let’s say that the measured Z_in was 100-j100-Ohms. The first step would be to normalize the input impedance by dividing Z_in by Z_0, which would result in 2-j2-Ohms. This opint can be located on the Smith chart, and from this point (2-j2), you can use a combination of inductors and capacitors to move the impedance to the necessary location on the Smith chart, which is the center of the chart where the red dot is in Figure 3. The table below helps better understand how each component affects the impedance of the matching network.
Using any combination of passive elements can be used to get measured impedance as close as possible to the center of the Smith chart for optimal performance. If we refer to the matching newtorks in Figure 4 and Figure 5, we can see that the matching network consists of the passive elements described in Table One.
Figure Five depicts the matching network reference design for the SAMB11 where the resistance network shown in the dotted square is omitted from the final design PCB. Also omitted was the capacitor laveld DNI (Do Not Include).
S-Parameters
Scattering parameters, or “S-parameters” are a set of parameters which define the electrical power delivered between two ports on a network, where a port is any where within the network containing voltage or current delivery [6]. The four parameters are displayed below:
The reflection coefficient referred to in the S11 description is defined as followed:
Where are the reflected and incident plane waves, and the is the intrinsic impedance of the medium the wave is traveling through, and is the intrinsic impedance of the surface/material medium the wave reflects or penetrates [5].
The S-parameters can be collected by using a Vector Network Analyzer, however they are fairly expensive, usually greater than $10,000 on the lower end models. As a substitute, there is software such as Microwave Office or Optenni which can calculate the S-parameters as well. While these software suites are NOT free, they do offer free “research” trials where you can use it free for a week (Microwave Office) or for a month (Optenni).
Optenni provides the most tutorials on how to get familiar with the basics of the software, and also offers an optimization tool which allows you to designate specific requirements you want for your design. For instance, in the case of the SAMB11 3DoTX board, the requirements for BLE is that it resonate at 2.4-GHz. By using Optenni, desired parameters can be chosen, and a matching circuit will be automatically constructed through the software. (Click Here, it will redirect you to the Optenni technical resource page).
Example
As seen in the S parameter chart in figure 6, the S11 parameter extends just beyond -20-dB. The figure therefore suggests that at approximately -20-dB the antenna radiates at its maximum. At 0-dB the antenna radiates nothing. While this simulation may look ideal, it is not practical for real world application. This is because the dark blue highlighted bandwidth (2.4-2.483-GHz) is difficult to realize in the physical world. In practical antenna circuits, the resonating frequency an antenna could transmit/receive is always met with some percentage of error, or acceptable deviation from nominal conditions. For example, the chip antenna we have chosen for the 3DoTX board has a frequency range from 2.4 to 2.5-GHz. A 100-MHz difference. By choosing more than the two components that have been shown below, more components can be added to open up the bandwidth of frequencies that can be received/transmitted by the antenna. Another great feature with Optenni is that you can tune the component values to see how each one effects the S11 parameter.
By looking at the smith chart in figure 7, we see that dark blue are highlighted on the graph corresponds with the dark blue area highlighted in figure 6. Recalling the information presented earlier about the smith chart and 50-Ohm impedances, we can see that the matching circuit accurately tunes the antenna to operate at the matched approximate 50-Ohm impedance.
In the matching circuit shown, the port corresponds with the input (i.e. the antenna) and the load corresponds with the SAMB11.
References
[1] Reference One
[2] Reference Two
[3] Reference Three
[4] Reference Four
[5] Fundamentals of Engineering Electromagnetics by David Cheng
[6] Reference Six
Acknowledgements
Thank you for Dr. Densmore, Dr. Rezvani, and Dr. Haggerty for help in contributing to understanding the matching network.























