add mmme3085 mechatronics week 4 lecture slides
This commit is contained in:
parent
11cd8df774
commit
0f29002415
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,39 @@
|
||||
enum daysOfWeek {SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY};
|
||||
int i = 0; // Number of the week days
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
for (i = 0; i < 7; i++){
|
||||
int day=daysOfWeek(i); //if it is Sunday, day will be 0, if Monday it will be 1 and so on
|
||||
Serial.print("Today is ");
|
||||
switch (day)
|
||||
{
|
||||
case SUNDAY:
|
||||
Serial.print("SUNDAY: Go for Swiming");
|
||||
break;
|
||||
case MONDAY:
|
||||
Serial.print("Monday: Go to Computer Engineering Lecture");
|
||||
break;
|
||||
case TUESDAY:
|
||||
Serial.print("Tuesday: Go to Computer Engineering Laboratory");
|
||||
break;
|
||||
case WEDNESDAY:
|
||||
Serial.print("Wednesday: Studay Mechatronics and Computer Engineering");
|
||||
break;
|
||||
case THURSDAY:
|
||||
Serial.print("Thursday: Go to Mechatronics Lecture");
|
||||
break;
|
||||
case FRIDAY:
|
||||
Serial.print("Friday: Go to Mechatronics Seminar");
|
||||
break;
|
||||
case SATURDAY:
|
||||
Serial.print("Saturday: Take a rest");
|
||||
break;
|
||||
}
|
||||
Serial.print('\n');
|
||||
delay(2000);
|
||||
}
|
||||
}
|
@ -0,0 +1,300 @@
|
||||
/* Example of driving servomotor and reading encoder signals in various ways */
|
||||
|
||||
#include <avr/io.h> /* Needed to set up counter on pin 47 */
|
||||
#include <SPI.h> /* Needed to communicate with LS7366R (Counter Click) */
|
||||
|
||||
/* Serial input aspects are based closely upon:
|
||||
http://forum.arduino.cc/index.php?topic=396450
|
||||
Example 4 - Receive a number as text and convert it to an int
|
||||
Modified to read a float */
|
||||
|
||||
/* LS7366R aspects very loosely based on concepts used in controlling
|
||||
the Robogaia 3-axis encoder shield though implementation is very different
|
||||
https://www.robogaia.com/3-axis-encoder-conter-arduino-shield.html */
|
||||
|
||||
/* Counting using Timer 5 (external counter input) based loosely on code from
|
||||
https://forum.arduino.cc/index.php?topic=59396.0 written by bubuldino */
|
||||
|
||||
/* Pins used for L298 driver */
|
||||
#define enA 13 /* PWM output, also visible as LED */
|
||||
#define in1 8 /* H bridge selection input 1 */
|
||||
#define in2 9 /* H bridge selection input 2 */
|
||||
#define minPercent -100.0
|
||||
#define maxPercent 100.0
|
||||
|
||||
/* Encoder input pins (used for state machine and interrupts) */
|
||||
#define channelA 2
|
||||
#define channelB 3
|
||||
|
||||
/* Used to to initiate SPI communication to LS7366R chip (Counter click) */
|
||||
#define chipSelectPin 10
|
||||
|
||||
/* Size of buffer used to store received characters */
|
||||
#define numChars 32
|
||||
|
||||
/* Intervals in milliseconds for user-defined timed loops */
|
||||
#define printInterval 1000
|
||||
|
||||
/* Global variables used in serial input */
|
||||
char receivedChars[numChars]; // an array to store the received data
|
||||
float dataNumber = 0; // new for this version
|
||||
boolean newData = false;
|
||||
|
||||
/* Global variables used for motor control and encoder reading */
|
||||
double percentSpeed;
|
||||
double encoderValue;
|
||||
|
||||
/* Used for state machine and encoder reading */
|
||||
typedef enum states{state1=1, state2, state3, state4};
|
||||
volatile long int count = 0;
|
||||
volatile long int error = 0;
|
||||
volatile states state;
|
||||
bool channelAState, channelBState;
|
||||
|
||||
/* Used for handling overflows in Timer 5 */
|
||||
volatile long int bigLaps;
|
||||
|
||||
/* Global variables used for loop timing */
|
||||
unsigned long prevMillisPrint = 0; /* stores last time values were printed */
|
||||
unsigned long prevMillisControl = 0; /* stores last time control action was updated */
|
||||
|
||||
/* Overlapping regions of memory used to convert four bytes to a long integer */
|
||||
union fourBytesToLong
|
||||
{
|
||||
long result;
|
||||
unsigned char bytes [4];
|
||||
};
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
Serial.println("Enter PWM duty cycle as a percentage (positive for forward, negative for reverse");
|
||||
|
||||
/* Set encoder pins as input but with pullup resistors to be compatible with various encoders */
|
||||
pinMode(channelA, INPUT_PULLUP);
|
||||
pinMode(channelB, INPUT_PULLUP);
|
||||
|
||||
channelAState = digitalRead(channelA);
|
||||
channelBState = digitalRead(channelB);
|
||||
|
||||
initialiseEncoderStateMachine(); /* Find initial state based on inputs */
|
||||
|
||||
/* Set up and initialise pin used for selecting LS7366R counter: hi=inactive */
|
||||
pinMode(chipSelectPin, OUTPUT);
|
||||
digitalWrite(chipSelectPin, HIGH);
|
||||
|
||||
SetUpLS7366RCounter();
|
||||
|
||||
delay(100);
|
||||
|
||||
/* Configure Timer 5 to count pulses on pin 47 */
|
||||
pinMode(47, INPUT_PULLUP); // set pin to input with pullup resistor
|
||||
|
||||
TCCR5A = 0; // No waveform generation needed.
|
||||
TCCR5B = (1<<CS50) | (1<<CS51) | (1<<CS52); // Normal mode, clock from pin T5 on rising edge. T5 is Arduinos Pin 47
|
||||
TCCR5C = 0; // No force output compare.
|
||||
TCNT5 = 0; // Initialise counter register to zero.
|
||||
TIMSK5= (1<<TOIE5); // Enable overflow interrupt
|
||||
sei(); // Enable all interrupts
|
||||
bigLaps = 0; // Initialise number of overflows
|
||||
|
||||
/* Configure control pins for L298 H bridge */
|
||||
pinMode(enA, OUTPUT);
|
||||
pinMode(in1, OUTPUT);
|
||||
pinMode(in2, OUTPUT);
|
||||
|
||||
/* Set initial rotation direction */
|
||||
digitalWrite(in1, LOW);
|
||||
digitalWrite(in2, HIGH);
|
||||
|
||||
//attachInterrupt(digitalPinToInterrupt(channelA), updateEncoderStateMachine, CHANGE);
|
||||
//attachInterrupt(digitalPinToInterrupt(channelB), updateEncoderStateMachine, CHANGE);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
unsigned long currentMillis = millis();
|
||||
|
||||
if (currentMillis - prevMillisPrint >= printInterval) {
|
||||
// save the last time you printed output
|
||||
prevMillisPrint = currentMillis;
|
||||
printLoop();
|
||||
}
|
||||
|
||||
recvWithEndMarker();
|
||||
if(convertNewNumber())
|
||||
// Update value read from serial line
|
||||
{
|
||||
percentSpeed=dataNumber;
|
||||
driveMotorPercent(percentSpeed);
|
||||
}
|
||||
|
||||
updateEncoderStateMachine();
|
||||
}
|
||||
|
||||
void driveMotorPercent(double percentSpeed)
|
||||
/* Output PWM and H bridge signals based on positive or negative duty cycle % */
|
||||
{
|
||||
percentSpeed = constrain(percentSpeed, -100, 100);
|
||||
int regVal = map(percentSpeed, -100, 100, -255, 255);
|
||||
analogWrite(enA, (int)abs(regVal));
|
||||
digitalWrite(in1, regVal>0);
|
||||
digitalWrite(in2, !(regVal>0));
|
||||
}
|
||||
|
||||
void printLoop()
|
||||
/* Print count and control information */
|
||||
{
|
||||
/* Sample all counters one after the other to avoid delay-related offsets */
|
||||
long encoderCountFromLS7366R = readEncoderCountFromLS7366R();
|
||||
long encoderCountFromStateMC = count;
|
||||
long stateMCerror = error;
|
||||
long timer5Count = TCNT5 + bigLaps*65536;
|
||||
Serial.print("Count from LS7366R = ");
|
||||
Serial.print(encoderCountFromLS7366R);
|
||||
Serial.print(" from state m/c = ");
|
||||
Serial.print(encoderCountFromStateMC);
|
||||
Serial.print(" State m/c errors = ");
|
||||
Serial.print(stateMCerror);
|
||||
Serial.print(" Count from LS7366R/4 = ");
|
||||
Serial.print(encoderCountFromLS7366R/4);
|
||||
Serial.print(" from Timer 5 = ");
|
||||
Serial.print(timer5Count);
|
||||
Serial.print(" Percent speed = ");
|
||||
Serial.print(percentSpeed);
|
||||
Serial.print("\r\n");
|
||||
}
|
||||
|
||||
long readEncoderCountFromLS7366R()
|
||||
/* Reads the LS7366R chip to obtain up/down count from encoder. Reads four
|
||||
bytes separately then concverts them to a long integer using a union */
|
||||
{
|
||||
fourBytesToLong converter; /* Union of four bytes and a long integer */
|
||||
|
||||
digitalWrite(chipSelectPin,LOW); /* Make LS7366R active */
|
||||
|
||||
SPI.transfer(0x60); // Request count
|
||||
converter.bytes[3] = SPI.transfer(0x00); /* Read highest order byte */
|
||||
converter.bytes[2] = SPI.transfer(0x00);
|
||||
converter.bytes[1] = SPI.transfer(0x00);
|
||||
converter.bytes[0] = SPI.transfer(0x00); /* Read lowest order byte */
|
||||
|
||||
digitalWrite(chipSelectPin,HIGH); /* Make LS7366R inactive */
|
||||
|
||||
return converter.result;
|
||||
}
|
||||
|
||||
|
||||
void SetUpLS7366RCounter(void)
|
||||
/* Initialiseds LS7366R hardware counter on Counter Click board to read quadrature signals */
|
||||
{
|
||||
/* Control registers in LS7366R - see LS7366R datasheet for this and subsequent control words */
|
||||
unsigned char IR = 0x00, MRD0=0x00;
|
||||
|
||||
// SPI initialization
|
||||
SPI.begin();
|
||||
//SPI.setClockDivider(SPI_CLOCK_DIV16); // SPI at 1Mhz (on 16Mhz clock)
|
||||
delay(10);
|
||||
|
||||
/* Configure as free-running 4x quadrature counter */
|
||||
digitalWrite(chipSelectPin,LOW); /* Select chip and initialise transfer */
|
||||
/* Instruction register IR */
|
||||
IR |= 0x80; /* Write to register (B7=1, B6=0) */
|
||||
IR |= 0x08; /* Select register MDR0: B5=0, B4=0, B3=1 */
|
||||
SPI.transfer(IR); /* Write to instruction register */
|
||||
/* Mode register 0 */
|
||||
MRD0 |= 0x03; /* 4x quadrature count: B0=1, B1=1 */
|
||||
/* B2=B3=0: free running. B4=B5=0: disable index. */
|
||||
/* B6=0: asynchronous index. B7: Filter division factor = 1. */
|
||||
SPI.transfer(MRD0);
|
||||
digitalWrite(chipSelectPin,HIGH);
|
||||
|
||||
/* Clear the counter i.e. set it to zero */
|
||||
IR = 0x00; /* Clear the instructino register IR */
|
||||
digitalWrite(chipSelectPin,LOW); /* Select chip and initialise transfer */
|
||||
IR |= 0x20; /* Select CNTR: B5=1,B4=0,B3=0; CLR register: B7=0,B6=0 */
|
||||
SPI.transfer(IR); /* Write to instruction register */
|
||||
digitalWrite(chipSelectPin,HIGH);
|
||||
|
||||
}
|
||||
|
||||
void recvWithEndMarker()
|
||||
/* Receive data from serial port finishing with "newline" character.
|
||||
Based on http://forum.arduino.cc/index.php?topic=396450 Example 4 */
|
||||
{
|
||||
static byte ndx = 0;
|
||||
char endMarker = '\n';
|
||||
char rc;
|
||||
|
||||
if (Serial.available() > 0) {
|
||||
rc = Serial.read();
|
||||
|
||||
if (rc != endMarker) {
|
||||
receivedChars[ndx] = rc;
|
||||
ndx++;
|
||||
if (ndx >= numChars) {
|
||||
ndx = numChars - 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
receivedChars[ndx] = '\0'; // terminate the string
|
||||
ndx = 0;
|
||||
newData = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool convertNewNumber()
|
||||
/* Converts character string to floating point number only if there are new
|
||||
data to convert, otherwise returns false */
|
||||
{
|
||||
if (newData) {
|
||||
dataNumber = 0.0; // new for this version
|
||||
dataNumber = atof(receivedChars); // new for this version
|
||||
newData = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void initialiseEncoderStateMachine()
|
||||
/* User written code to initialise state of state machine code based on input states */
|
||||
{
|
||||
if (channelAState)
|
||||
{
|
||||
if(channelBState)
|
||||
{
|
||||
state = state3;
|
||||
}
|
||||
/* else.... a lot of code goes here! */
|
||||
}
|
||||
}
|
||||
|
||||
void updateEncoderStateMachine()
|
||||
/* User written code to update state and increment count of state machine */
|
||||
{
|
||||
channelAState = digitalRead(channelA);
|
||||
channelBState = digitalRead(channelB);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case state1:
|
||||
if (channelAState && !channelBState)
|
||||
{
|
||||
count++;
|
||||
state = state2;
|
||||
}
|
||||
/* else if .... a lot of code goes here! */
|
||||
/* don't forget "break" at end of each case. */
|
||||
}
|
||||
}
|
||||
|
||||
ISR(TIMER5_OVF_vect )
|
||||
{
|
||||
//when this runs, you had 65536 pulses counted.
|
||||
bigLaps++;
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
const int NumStates = 8;
|
||||
int state = 0;
|
||||
byte StateTable [NumStates][2]={
|
||||
{0x88, 1},
|
||||
{0xC8, 2},
|
||||
{0x28, 5},
|
||||
{0x48, 2},
|
||||
{0x88, 1},
|
||||
{0x8C, 2},
|
||||
{0x82, 5},
|
||||
{0x84, 2}};
|
||||
|
||||
void setup() {
|
||||
DDRA = 0xFF; // Set PORTA as output
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print(state);
|
||||
Serial.print(' ');
|
||||
PORTA = StateTable[state][0];
|
||||
Serial.print(PORTA, HEX);
|
||||
Serial.print(' ');
|
||||
Serial.print("Waiting Time is:");
|
||||
Serial.print(StateTable[state][1]);
|
||||
Serial.print('\n');
|
||||
delay(StateTable[state][1]*1000);
|
||||
|
||||
if(state < NumStates-1)
|
||||
{
|
||||
state++;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
const int NumStates = 8;
|
||||
int state = 0;
|
||||
byte StateTable [NumStates][3]={
|
||||
{0x88, 1, 0},
|
||||
{0xC8, 2, 0},
|
||||
{0x28, 5, 1},
|
||||
{0x48, 2, 0},
|
||||
{0x88, 1, 0},
|
||||
{0x8C, 2, 0},
|
||||
{0x82, 5, 0},
|
||||
{0x84, 2, 0}};
|
||||
void setup() {
|
||||
DDRA = 0xFF; // Set PORTA as output
|
||||
Serial.begin(9600);
|
||||
}
|
||||
void loop() {
|
||||
Serial.print(state);
|
||||
Serial.print(' ');
|
||||
PORTA = StateTable[state][0];
|
||||
Serial.print(PORTA, HEX);
|
||||
Serial.print(' ');
|
||||
Serial.print("Waiting Time is:");
|
||||
Serial.print(StateTable[state][1]);
|
||||
Serial.print('\n');
|
||||
delay(StateTable[state][1]*1000);
|
||||
while(StateTable[state][3] && !(PINB & 0x01));
|
||||
{
|
||||
// Just wait here if StateTable[state][3] = 1 and Pin No 1 on Port B goes low (0).
|
||||
}
|
||||
if(state < NumStates-1)
|
||||
{
|
||||
state++;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 0;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user