add skeleton programs
This commit is contained in:
300
Lab_1/skeleton_programs/MotorEncoderSkeleton.ino
Normal file
300
Lab_1/skeleton_programs/MotorEncoderSkeleton.ino
Normal file
@@ -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++;
|
||||||
|
}
|
||||||
|
|
||||||
87
Lab_1/skeleton_programs/TestEncoder.c
Normal file
87
Lab_1/skeleton_programs/TestEncoder.c
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#define bool int
|
||||||
|
#define byte unsigned char
|
||||||
|
#define numChars 32
|
||||||
|
|
||||||
|
void initialiseEncoderStateMachine();
|
||||||
|
void updateEncoderStateMachine();
|
||||||
|
|
||||||
|
// Here we are using global variables simply to be compatible with the Arduino program structure
|
||||||
|
// This is REALLY bad practice so please don't do it otherwise!
|
||||||
|
long int count = 0;
|
||||||
|
long int error = 0;
|
||||||
|
|
||||||
|
enum states {state1=1, state2, state3, state4};
|
||||||
|
bool channelAState=0;
|
||||||
|
bool channelBState=0;
|
||||||
|
|
||||||
|
enum states state;
|
||||||
|
char receivedChars[numChars]="00"; // an array to store the received data
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// Replicates the setup in Arduino
|
||||||
|
printf("Enter a pair of characters representing initial states of channels A and B\n");
|
||||||
|
scanf("%s",receivedChars);
|
||||||
|
channelAState = receivedChars[0]!='0';
|
||||||
|
channelBState = receivedChars[1]!='0';
|
||||||
|
|
||||||
|
initialiseEncoderStateMachine();
|
||||||
|
printf("State %d, count %ld, error %ld\n", state, count, error);
|
||||||
|
printf("Enter a pair of characters representing channels A and B, enter 99 to end\n");
|
||||||
|
|
||||||
|
// Replicates the loop in Arduino
|
||||||
|
do
|
||||||
|
{
|
||||||
|
scanf("%s",receivedChars);
|
||||||
|
if (strcmp(receivedChars, "99")==0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
channelAState = receivedChars[0]!='0';
|
||||||
|
channelBState = receivedChars[1]!='0';
|
||||||
|
updateEncoderStateMachine();
|
||||||
|
printf("State %d, count %ld, error %ld\n", state, count, error);
|
||||||
|
|
||||||
|
}
|
||||||
|
while(1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void initialiseEncoderStateMachine()
|
||||||
|
{
|
||||||
|
/* If initially A is 0 and B is 0, system starts in State 1
|
||||||
|
If initially A is 1 and B is 0, system starts in State 2
|
||||||
|
If initially A is 1 and B is 1, system starts in State 3
|
||||||
|
If initially A is 0 and B is 1, system starts in State 4 */
|
||||||
|
|
||||||
|
if (channelAState)
|
||||||
|
{
|
||||||
|
if(channelBState)
|
||||||
|
{
|
||||||
|
state = state3;
|
||||||
|
}
|
||||||
|
/* else .... lots of code goes here */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateEncoderStateMachine()
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case state1:
|
||||||
|
/* If A is 0 and B is 0, do nothing and stay in State 1
|
||||||
|
If A is 1 and B is 0, add 1 to main counter and go to State 2
|
||||||
|
If A is 0 and B is 1, subtract 1 to main counter and go to State 4
|
||||||
|
If A is 1 and B is 1, do nothing to main counter but add 1 to error counter and go to state 3 */
|
||||||
|
|
||||||
|
if (channelAState && !channelBState)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
state = state2;
|
||||||
|
}
|
||||||
|
/* else .... lots of code goes here */
|
||||||
|
break; /* don't forget break at the end of each case! */
|
||||||
|
}
|
||||||
|
}
|
||||||
116
Lab_1/skeleton_programs/TestEncoder.ino
Normal file
116
Lab_1/skeleton_programs/TestEncoder.ino
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
/* Test program for incremental encoder state machine code */
|
||||||
|
/* 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 */
|
||||||
|
|
||||||
|
long int count = 0;
|
||||||
|
long int error = 0;
|
||||||
|
enum states{state1=1, state2, state3, state4};
|
||||||
|
bool channelAState;
|
||||||
|
bool channelBState;
|
||||||
|
|
||||||
|
int state;
|
||||||
|
const byte numChars = 32;
|
||||||
|
char receivedChars[numChars]; // an array to store the received data
|
||||||
|
|
||||||
|
boolean newData = false;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
Serial.println("Enter initial state as a 2-digit number e.g. 01 then hit return");
|
||||||
|
do {
|
||||||
|
recvWithEndMarker();
|
||||||
|
} while (!newData);
|
||||||
|
channelAState = receivedChars[0]!='0';
|
||||||
|
channelBState = receivedChars[1]!='0';
|
||||||
|
|
||||||
|
initialiseEncoderStateMachine();
|
||||||
|
Serial.print(state);
|
||||||
|
Serial.print('\n');
|
||||||
|
|
||||||
|
Serial.println("Now keep entering state as a 2-digit number e.g. 01 then hit return.");
|
||||||
|
newData = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
recvWithEndMarker();
|
||||||
|
if (newData)
|
||||||
|
{
|
||||||
|
channelAState = receivedChars[0]!='0';
|
||||||
|
channelBState = receivedChars[1]!='0';
|
||||||
|
updateEncoderStateMachine();
|
||||||
|
Serial.print("State: ");
|
||||||
|
Serial.print((int)state);
|
||||||
|
Serial.print(" Count: ");
|
||||||
|
Serial.print(count);
|
||||||
|
Serial.print(" Error: ");
|
||||||
|
Serial.print(error);
|
||||||
|
Serial.write('\n');
|
||||||
|
newData = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void recvWithEndMarker() {
|
||||||
|
static byte ndx = 0;
|
||||||
|
char endMarker = '\n';
|
||||||
|
char rc;
|
||||||
|
|
||||||
|
while (Serial.available() > 0 && newData == false) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialiseEncoderStateMachine()
|
||||||
|
{
|
||||||
|
/* If initially A is 0 and B is 0, system starts in State 1
|
||||||
|
If initially A is 1 and B is 0, system starts in State 2
|
||||||
|
If initially A is 1 and B is 1, system starts in State 3
|
||||||
|
If initially A is 0 and B is 1, system starts in State 4 */
|
||||||
|
|
||||||
|
if (channelAState)
|
||||||
|
{
|
||||||
|
if(channelBState)
|
||||||
|
{
|
||||||
|
state = state3;
|
||||||
|
}
|
||||||
|
/* else .... lots of code goes here */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateEncoderStateMachine()
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case state1:
|
||||||
|
/* If A is 0 and B is 0, do nothing and stay in State 1
|
||||||
|
If A is 1 and B is 0, add 1 to main counter and go to State 2
|
||||||
|
If A is 0 and B is 1, subtract 1 to main counter and go to State 4
|
||||||
|
If A is 1 and B is 1, do nothing to main counter but add 1 to error counter and go to state 3 */
|
||||||
|
|
||||||
|
if (channelAState && !channelBState)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
state = state2;
|
||||||
|
}
|
||||||
|
/* else .... lots of code goes here */
|
||||||
|
break; /* don't forget break at the end of each case! */
|
||||||
|
/* other cases follow */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
135
Lab_1/skeleton_programs/TwoSensorsSkeleton.c
Normal file
135
Lab_1/skeleton_programs/TwoSensorsSkeleton.c
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
// Forward TC function
|
||||||
|
float NISTdegCtoMilliVoltsKtype(float tempDegC); // returns EMF in millivolts
|
||||||
|
|
||||||
|
// Inverse TC function
|
||||||
|
float NISTmilliVoltsToDegCKtype(float tcEMFmV); // returns temp in degC assuming 0 degC cold jcn
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// Define VRef
|
||||||
|
|
||||||
|
// Define Thermistor constants
|
||||||
|
|
||||||
|
// User input for pins A0 and A1
|
||||||
|
|
||||||
|
// Calculate thermistor temperature in degrees C ( Part b, i,ii,iii & v)
|
||||||
|
|
||||||
|
// Calculate thermocouple temperature in degrees C ( Part c, i - iv)
|
||||||
|
|
||||||
|
// Output results
|
||||||
|
printf("Thermistor temperature (deg C): %f \n", *******);
|
||||||
|
printf("Thermocouple temperature with CJC (deg C): %f \n", ******);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write a function here to convert ADC value to voltages. (Part a, equation 1)
|
||||||
|
Call it from the main() function above */
|
||||||
|
|
||||||
|
/* Write a function to convert degrees K to degrees C (Part b, (iv))
|
||||||
|
Call it from the main() function above */
|
||||||
|
|
||||||
|
/* returns EMF in millivolts */
|
||||||
|
float NISTdegCtoMilliVoltsKtype(float tempDegC)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
float milliVolts = 0;
|
||||||
|
if(tempDegC >= -170 && tempDegC < 0)
|
||||||
|
{
|
||||||
|
const float coeffs[11] =
|
||||||
|
{
|
||||||
|
0.000000000000E+00,
|
||||||
|
0.394501280250E-01,
|
||||||
|
0.236223735980E-04,
|
||||||
|
-0.328589067840E-06,
|
||||||
|
-0.499048287770E-08,
|
||||||
|
-0.675090591730E-10,
|
||||||
|
-0.574103274280E-12,
|
||||||
|
-0.310888728940E-14,
|
||||||
|
-0.104516093650E-16,
|
||||||
|
-0.198892668780E-19,
|
||||||
|
-0.163226974860E-22
|
||||||
|
};
|
||||||
|
for (i=0; i<=10; i++)
|
||||||
|
{
|
||||||
|
milliVolts += coeffs[i] * pow(tempDegC,i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(tempDegC >= 0 && tempDegC <= 1372)
|
||||||
|
{
|
||||||
|
const float coeffs[10] =
|
||||||
|
{
|
||||||
|
-0.176004136860E-01,
|
||||||
|
0.389212049750E-01,
|
||||||
|
0.185587700320E-04,
|
||||||
|
-0.994575928740E-07,
|
||||||
|
0.318409457190E-09,
|
||||||
|
-0.560728448890E-12,
|
||||||
|
0.560750590590E-15,
|
||||||
|
-0.320207200030E-18,
|
||||||
|
0.971511471520E-22,
|
||||||
|
-0.121047212750E-25
|
||||||
|
};
|
||||||
|
const float a0 = 0.118597600000E+00;
|
||||||
|
const float a1 = -0.118343200000E-03;
|
||||||
|
const float a2 = 0.126968600000E+03;
|
||||||
|
|
||||||
|
for (i=0; i<=9; i++)
|
||||||
|
{
|
||||||
|
milliVolts += coeffs[i] * pow(tempDegC,i);
|
||||||
|
}
|
||||||
|
|
||||||
|
milliVolts += a0*exp(a1*(tempDegC - a2)*(tempDegC - a2));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
milliVolts = 99E99;
|
||||||
|
}
|
||||||
|
return milliVolts;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns temperature in deg C.
|
||||||
|
float NISTmilliVoltsToDegCKtype(float tcEMFmV)
|
||||||
|
{
|
||||||
|
|
||||||
|
int i, j;
|
||||||
|
float tempDegC = 0;
|
||||||
|
const float coeffs[11][3] =
|
||||||
|
{
|
||||||
|
{0.0000000E+00, 0.000000E+00, -1.318058E+02},
|
||||||
|
{2.5173462E+01, 2.508355E+01, 4.830222E+01},
|
||||||
|
{-1.1662878E+00, 7.860106E-02, -1.646031E+00},
|
||||||
|
{-1.0833638E+00, -2.503131E-01, 5.464731E-02},
|
||||||
|
{-8.9773540E-01, 8.315270E-02, -9.650715E-04},
|
||||||
|
{-3.7342377E-01, -1.228034E-02, 8.802193E-06},
|
||||||
|
{-8.6632643E-02, 9.804036E-04, -3.110810E-08},
|
||||||
|
{-1.0450598E-02, -4.413030E-05, 0.000000E+00},
|
||||||
|
{-5.1920577E-04, 1.057734E-06, 0.000000E+00},
|
||||||
|
{0.0000000E+00, -1.052755E-08, 0.000000E+00}
|
||||||
|
};
|
||||||
|
if(tcEMFmV >=-5.891 && tcEMFmV <=0 )
|
||||||
|
{
|
||||||
|
j=0;
|
||||||
|
}
|
||||||
|
else if (tcEMFmV > 0 && tcEMFmV <=20.644 )
|
||||||
|
{
|
||||||
|
j=1;
|
||||||
|
}
|
||||||
|
else if (tcEMFmV > 20.644 && tcEMFmV <=54.886 )
|
||||||
|
{
|
||||||
|
j=2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 99E9;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<=9; i++)
|
||||||
|
{
|
||||||
|
tempDegC += coeffs[i][j] * pow(tcEMFmV,i);
|
||||||
|
}
|
||||||
|
return tempDegC;
|
||||||
|
}
|
||||||
143
Lab_1/skeleton_programs/TwoSensorsSkeleton.ino
Normal file
143
Lab_1/skeleton_programs/TwoSensorsSkeleton.ino
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
/* Test program for reading of thermistor, thermocouple and LVDT.
|
||||||
|
K-type thermocouple functions written by Arthur Jones using
|
||||||
|
official NIST polynomial data from
|
||||||
|
https://srdata.nist.gov/its90/download/type_k.tab */
|
||||||
|
|
||||||
|
#include <math.h> /* needed for exp() and pow() */
|
||||||
|
|
||||||
|
/* It is good practice to define things like pins used at the start
|
||||||
|
so that you avoid hard-coded values (magic numbers) in code */
|
||||||
|
#define TCpin A0
|
||||||
|
#define ThermistorPin A1
|
||||||
|
|
||||||
|
/* Similarly, define any constant values e.g. Vref, B, R0 here to avoid
|
||||||
|
need for "magic numbers" in code */
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(9600);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
/* Put your code here to read ADCs and convert ADC voltages to
|
||||||
|
temperatures */
|
||||||
|
|
||||||
|
/* Display results. Don't use printf or formatting etc., they don't work on the Arduino. Just use
|
||||||
|
the serial print statements given here, inserting your own code as needed */
|
||||||
|
Serial.print("Thermistor temperature (deg C): ");
|
||||||
|
Serial.println(.........); // Replace ... with your code, it won't compile until you do.
|
||||||
|
Serial.print(" Thermocouple temperature with CJC (deg C): ");
|
||||||
|
Serial.println(.........); // Replace ... with your code, it won't compile until you do.
|
||||||
|
Serial.println("\n");
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write a function to convert ADC value to
|
||||||
|
voltage: put it here and use it in your code above*/
|
||||||
|
|
||||||
|
/* Write a function to convert degrees K to degrees C
|
||||||
|
Call it from the main() function above */
|
||||||
|
|
||||||
|
/* Under no circumstances change any of the following code, it is fine as it is */
|
||||||
|
float NISTdegCtoMilliVoltsKtype(float tempDegC)
|
||||||
|
/* returns EMF in millivolts */
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
float milliVolts = 0;
|
||||||
|
if(tempDegC >= -170 && tempDegC < 0)
|
||||||
|
{
|
||||||
|
const float coeffs[11] =
|
||||||
|
{
|
||||||
|
0.000000000000E+00,
|
||||||
|
0.394501280250E-01,
|
||||||
|
0.236223735980E-04,
|
||||||
|
-0.328589067840E-06,
|
||||||
|
-0.499048287770E-08,
|
||||||
|
-0.675090591730E-10,
|
||||||
|
-0.574103274280E-12,
|
||||||
|
-0.310888728940E-14,
|
||||||
|
-0.104516093650E-16,
|
||||||
|
-0.198892668780E-19,
|
||||||
|
-0.163226974860E-22
|
||||||
|
};
|
||||||
|
for (i=0; i<=10; i++)
|
||||||
|
{
|
||||||
|
milliVolts += coeffs[i] * pow(tempDegC,i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(tempDegC >= 0 && tempDegC <= 1372)
|
||||||
|
{
|
||||||
|
const float coeffs[10] =
|
||||||
|
{
|
||||||
|
-0.176004136860E-01,
|
||||||
|
0.389212049750E-01,
|
||||||
|
0.185587700320E-04,
|
||||||
|
-0.994575928740E-07,
|
||||||
|
0.318409457190E-09,
|
||||||
|
-0.560728448890E-12,
|
||||||
|
0.560750590590E-15,
|
||||||
|
-0.320207200030E-18,
|
||||||
|
0.971511471520E-22,
|
||||||
|
-0.121047212750E-25
|
||||||
|
};
|
||||||
|
const float a0 = 0.118597600000E+00;
|
||||||
|
const float a1 = -0.118343200000E-03;
|
||||||
|
const float a2 = 0.126968600000E+03;
|
||||||
|
|
||||||
|
for (i=0; i<=9; i++)
|
||||||
|
{
|
||||||
|
milliVolts += coeffs[i] * pow(tempDegC,i);
|
||||||
|
}
|
||||||
|
|
||||||
|
milliVolts += a0*exp(a1*(tempDegC - a2)*(tempDegC - a2));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
milliVolts = 99E9;
|
||||||
|
}
|
||||||
|
return milliVolts;
|
||||||
|
}
|
||||||
|
|
||||||
|
float NISTmilliVoltsToDegCKtype(float tcEMFmV)
|
||||||
|
// returns temperature in deg C.
|
||||||
|
{
|
||||||
|
|
||||||
|
int i, j;
|
||||||
|
float tempDegC = 0;
|
||||||
|
const float coeffs[11][3] =
|
||||||
|
{
|
||||||
|
{0.0000000E+00, 0.000000E+00, -1.318058E+02},
|
||||||
|
{2.5173462E+01, 2.508355E+01, 4.830222E+01},
|
||||||
|
{-1.1662878E+00, 7.860106E-02, -1.646031E+00},
|
||||||
|
{-1.0833638E+00, -2.503131E-01, 5.464731E-02},
|
||||||
|
{-8.9773540E-01, 8.315270E-02, -9.650715E-04},
|
||||||
|
{-3.7342377E-01, -1.228034E-02, 8.802193E-06},
|
||||||
|
{-8.6632643E-02, 9.804036E-04, -3.110810E-08},
|
||||||
|
{-1.0450598E-02, -4.413030E-05, 0.000000E+00},
|
||||||
|
{-5.1920577E-04, 1.057734E-06, 0.000000E+00},
|
||||||
|
{0.0000000E+00, -1.052755E-08, 0.000000E+00}
|
||||||
|
};
|
||||||
|
if(tcEMFmV >=-5.891 && tcEMFmV <=0 )
|
||||||
|
{
|
||||||
|
j=0;
|
||||||
|
}
|
||||||
|
else if (tcEMFmV > 0 && tcEMFmV <=20.644 )
|
||||||
|
{
|
||||||
|
j=1;
|
||||||
|
}
|
||||||
|
else if (tcEMFmV > 20.644 && tcEMFmV <=54.886 )
|
||||||
|
{
|
||||||
|
j=2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 99E9;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<=9; i++)
|
||||||
|
{
|
||||||
|
tempDegC += coeffs[i][j] * pow(tcEMFmV,i);
|
||||||
|
}
|
||||||
|
return tempDegC;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user