Post by whitelion on Dec 17, 2018 1:28:42 GMT
To Whom It May Concern,
I apologize in advance for the long post but I wanted to give whoever is interested in helping enough information. I have developed an Arduino shield that makes extensive use of the SPI buss. I initially developed this hardware and got everything working using an Arduino Due but have moved to the ShieldBuddy for computational reasons (I need a faster sample rate for the system I am controlling). The idea is to use one core to handle commands and data from the host and the other core(s) to do the number crunching. In addition the ShieldBuddy is 200MHz whereas the Due is 84MHz. I have been using Megunolink (https://www.megunolink.com) to handle the transfer of data and commands across the serial port between the host (Intel NUC) and the ShieldBuddy. I have successfully used this software with the ShieldBuddy but I am having problems using the SPI library with the ShieldBuddy. The devices on the SPI buss are:
1.) 2 16 bit D2A converters using pins 9 and 10 for CS, MAX541(data sheet not attached due to post limits)
2.) 1 16 bit A2D converter using pin 11 for CS, AD977 (data sheet attached)
3.) 2 UFDC smart chips used to measure the period of a 555 timer that indicates the water level in my application. These chips use pins 8 and 12 for the chip select. (data sheet attached)AD977_977A.pdf (284.03 KB)UFDC_1.pdf (490.3 KB)
I managed to get the D2A converters working using 2 8 bit transfers since the ShieldBuddy SPI library doesn't explicitly have a 16 bit transfer defined. Right now I am having difficulty with the A2D chip. Below is a screen shot of the A2D read sequence. The chip select is shown in yellow. The magenta is the read/convert (RC) pin which tells the chip to start a new conversion. The chip echos back a change in the BUSY' signal when the conversion is done (BUSY' not shown). The software function read_A2D_voltage() then uses the SPI library functions to read the MISO data (dark blue). I use two 8 bit transfers to read the MISO data which is organized as MSBFIRST. The cyan signal is SCK. The third 8 bit transfer is needed to stabilize the MISO signal, for some reason without this the end and start of the MISO signal seems unstable. I had to do something similar to this with the Due implementation but it did work. I think this is just a problem with this particular make of chip. At any rate the last transfer is not used. Two things are wrong with the MISO signal. First the chip is being used to measure a 0-5V signal with the voltage at 3.3029 Volts. Since the voltage is greater than 2.5 I expect the first bit to a 1 but whether the data is clocked in on a rising or falling edge of the SCK it is a 0 which doesn't make sense to me. Second the data read by the software is not the same as is shown on the scope. I am getting received values like
0010 0000 0000 0001 (binary)
8193 (decimal)
Voltage = 0.6250858306
which is not the same bit stream I see on the scope. I'm not sure what the issues are or how to debug this problem further. I am probably not using the SPI library correctly but it would help if I could use a 16 bit transfer. If someone could help how I should be using the SPI library and using a 16 bit transfer that would help.
Thanks in advance for any help anyone can provide. I have attached my sketch with is in a bit of disarray since I am in the middle of debugging but please focus on the code for core 1 which is where I try to read my A2D chip.
-Joel

I apologize in advance for the long post but I wanted to give whoever is interested in helping enough information. I have developed an Arduino shield that makes extensive use of the SPI buss. I initially developed this hardware and got everything working using an Arduino Due but have moved to the ShieldBuddy for computational reasons (I need a faster sample rate for the system I am controlling). The idea is to use one core to handle commands and data from the host and the other core(s) to do the number crunching. In addition the ShieldBuddy is 200MHz whereas the Due is 84MHz. I have been using Megunolink (https://www.megunolink.com) to handle the transfer of data and commands across the serial port between the host (Intel NUC) and the ShieldBuddy. I have successfully used this software with the ShieldBuddy but I am having problems using the SPI library with the ShieldBuddy. The devices on the SPI buss are:
1.) 2 16 bit D2A converters using pins 9 and 10 for CS, MAX541(data sheet not attached due to post limits)
2.) 1 16 bit A2D converter using pin 11 for CS, AD977 (data sheet attached)
3.) 2 UFDC smart chips used to measure the period of a 555 timer that indicates the water level in my application. These chips use pins 8 and 12 for the chip select. (data sheet attached)AD977_977A.pdf (284.03 KB)UFDC_1.pdf (490.3 KB)
I managed to get the D2A converters working using 2 8 bit transfers since the ShieldBuddy SPI library doesn't explicitly have a 16 bit transfer defined. Right now I am having difficulty with the A2D chip. Below is a screen shot of the A2D read sequence. The chip select is shown in yellow. The magenta is the read/convert (RC) pin which tells the chip to start a new conversion. The chip echos back a change in the BUSY' signal when the conversion is done (BUSY' not shown). The software function read_A2D_voltage() then uses the SPI library functions to read the MISO data (dark blue). I use two 8 bit transfers to read the MISO data which is organized as MSBFIRST. The cyan signal is SCK. The third 8 bit transfer is needed to stabilize the MISO signal, for some reason without this the end and start of the MISO signal seems unstable. I had to do something similar to this with the Due implementation but it did work. I think this is just a problem with this particular make of chip. At any rate the last transfer is not used. Two things are wrong with the MISO signal. First the chip is being used to measure a 0-5V signal with the voltage at 3.3029 Volts. Since the voltage is greater than 2.5 I expect the first bit to a 1 but whether the data is clocked in on a rising or falling edge of the SCK it is a 0 which doesn't make sense to me. Second the data read by the software is not the same as is shown on the scope. I am getting received values like
0010 0000 0000 0001 (binary)
8193 (decimal)
Voltage = 0.6250858306
which is not the same bit stream I see on the scope. I'm not sure what the issues are or how to debug this problem further. I am probably not using the SPI library correctly but it would help if I could use a 16 bit transfer. If someone could help how I should be using the SPI library and using a 16 bit transfer that would help.
Thanks in advance for any help anyone can provide. I have attached my sketch with is in a bit of disarray since I am in the middle of debugging but please focus on the code for core 1 which is where I try to read my A2D chip.
-Joel

#include <MegunoLink.h>
#include <CommandHandler.h>
#include <TCPCommandHandler.h>
#include <ArduinoTimer.h>
#include <CircularBuffer.h>
//#include <EEPROMStore.h>
#include <Filter.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <SPI.h>
#include <SpiIf.h>
#include <Metro.h>
# define Serial SerialASC
//#define PI 3.14159265358979
/*** Don't worry, the normal Arduino setup() and loop() are below this block! ***/
/* LMU uninitialised data */
StartOfUninitialised_LMURam_Variables
/* Put your LMU RAM fast access variables that have no initial values here e.g. uint32 LMU_var; */
EndOfUninitialised_LMURam_Variables
/* LMU uninitialised data */
StartOfInitialised_LMURam_Variables
/* Put your LMU RAM fast access variables that have an initial value here e.g. uint32 LMU_var_init = 1; */
EndOfInitialised_LMURam_Variables
/* If you do not care where variables end up, declare them here! */
void MessageLogger_CSVData(long, float, float, float, float, float, String);
//TimePlot MyPlot("Test Time Plot",SerialASC);
TimePlot AnglePlot("Beam Angle",SerialASC); // Channel name
TimePlot AngularRatePlot("Beam Angular Rate",SerialASC); // Channel name
TimePlot WaterLevelPlot("Water Levels",SerialASC);
TimePlot TemperaturePlot("Water Temperature",SerialASC);
TimePlot ControlInputPlot("Control Voltages",SerialASC);
CommandHandler<> SerialCommandHandler;
Metro ISRMetroCore0 = Metro(50); // 60 ms
/*** Core 0 ***/
const int CORE0HB = 2;
int CORE0HB_flag = 0;
boolean PUMP_CONTROL_STATE = false;
boolean BEAM_CONTROL_STATE = false;
#define Nv 6
#define Np 5
#define Npf 2
#define Nbf 2
float xk_v[Nv] = {0.0,0.0,0.0,0.0,0.0,0.0};
float xk_p[Np] = {0.0,0.0,0.0,0.0,0.0};
float xk_pf[Npf] = {0.0,0.0};
float xk_bf[Nbf] = {0.0,0.0};
unsigned long timer;
unsigned long timer_setup;
//float theta = 0.0;
float theta_dot_est = 1.0;
float delta_h = 3.0; // right - left
float water_temperature_ave = 32.0;
float input_Vr_core0 = 1.2;
float input_Vl_core0 = 3.4;
float PumpIdleVoltageRight = 0.0;
float PumpIdleVoltageLeft = 0.0;
float delta_h_ref_pc = 0.0;
float theta_ref = 0.0;
float kp = 200.0;
void setup() {
// put your setup code for core 0 here, to run once:
pinMode(CORE0HB, OUTPUT);
digitalWrite(CORE0HB,HIGH); // start out high
// Serial.begin(115200);
// MyPlot.SetTitle("Test Plot Title");
AnglePlot.SetTitle("Hallpot Angle Measurement");
AnglePlot.SetXlabel("Time (sec.)");
AnglePlot.SetYlabel("Angle (deg.)");
AnglePlot.SetSeriesProperties("Calibrated Hallpot Angle", TimePlot::Red, TimePlot::Solid, 3, TimePlot::Plus); // legend tag
AngularRatePlot.SetTitle("Estimated Angular Rate");
AngularRatePlot.SetXlabel("Time (sec.)");
AngularRatePlot.SetYlabel("Angular Rate (deg./sec.)");
AngularRatePlot.SetSeriesProperties("Estimated Angular Rate", TimePlot::Red, TimePlot::Solid, 3, TimePlot::Plus);
WaterLevelPlot.SetTitle("Water Level Measurements");
WaterLevelPlot.SetXlabel("Time (sec.)");
WaterLevelPlot.SetYlabel("Height (m)");
WaterLevelPlot.SetSeriesProperties("Calibrated Water Level (Right - Left)", TimePlot::Blue, TimePlot::Solid, 3, TimePlot::Plus);
TemperaturePlot.SetTitle("Temperature Measurements");
TemperaturePlot.SetXlabel("Time (sec.)");
TemperaturePlot.SetYlabel("Temperature (deg. C)");
TemperaturePlot.SetSeriesProperties("Calibrated Water Temperature (Average)", TimePlot::Green, TimePlot::Solid, 3, TimePlot::Plus);
ControlInputPlot.SetTitle("Control Input Voltages");
ControlInputPlot.SetXlabel("Time (sec.)");
ControlInputPlot.SetYlabel("Voltage (V)");
ControlInputPlot.SetSeriesProperties("Right Pump Voltage", TimePlot::Magenta, TimePlot::Solid, 3, TimePlot::Plus);
ControlInputPlot.SetSeriesProperties("Left Pump Voltage", TimePlot::Cyan, TimePlot::Solid, 3, TimePlot::Plus);
SerialCommandHandler.AddVariable(F("PumpIdleVoltageRight"), PumpIdleVoltageRight);
SerialCommandHandler.AddVariable(F("PumpIdleVoltageLeft"), PumpIdleVoltageLeft);
SerialCommandHandler.SetDefaultHandler(Cmd_Unknown);
SerialCommandHandler.AddCommand(F("WHCCheckBoxEvent"), Cmd_WHCCheckBoxEvent);
SerialCommandHandler.AddCommand(F("BACCheckBoxEvent"), Cmd_BACCheckBoxEvent);
SerialCommandHandler.AddCommand(F("ZeroFBCStates"), Cmd_BACZeroStates);
SerialCommandHandler.AddVariable(F("ReferenceWaterHeight"), delta_h_ref_pc);
SerialCommandHandler.AddVariable(F("ReferenceBeamAngle"), theta_ref);
SerialCommandHandler.AddVariable(F("Kp"), kp);
timer_setup = millis();
}
void loop() {
SerialCommandHandler.Process();
if (ISRMetroCore0.check() == 1)
{
// put your main code for core 0 here, to run repeatedly:
// AnglePlot.SendFloatData("Calibrated Hallpot Angle", theta, 4);
// AngularRatePlot.SendFloatData("Estimated Angular Rate", theta_dot_est, 4);
// WaterLevelPlot.SendFloatData("Calibrated Water Level (Right - Left)", delta_h, 4); // delta_h
// TemperaturePlot.SendFloatData("Calibrated Water Temperature (Average)", water_temperature_ave, 4); // water_temperature_average
// ControlInputPlot.SendFloatData("Right Pump Voltage", input_Vr_core0, 4);
// ControlInputPlot.SendFloatData("Left Pump Voltage", input_Vl_core0, 4);
// timer = millis() - timer_setup;
// MessageLogger_CSVData(timer, water_temperature_ave, delta_h, theta, theta_dot_est, input_Vr_core0, input_Vl_core0, "Sensor_Actuator_Data");
// //MessageLogger_CSVData(timer, water_temperature_average, delta_h, UFDC_sig_right, UFDC_sig_left, input_Vr, input_Vl, "Sensor_Actuator_Data");
CORE0HB_flag = !CORE0HB_flag;
digitalWrite(CORE0HB,CORE0HB_flag);
}
}
void MessageLogger_CSVData(long time, float data1, float data2, float data3, float data4, float data5, float data6, String channelName)
{
Serial.print("{MESSAGE:");
Serial.print(channelName);
Serial.print("|data|");
Serial.print(time);
Serial.print(",");
Serial.print(data1,2); // 2 is number of digits to right of decimal
Serial.print(",");
Serial.print(data2,4); // 4
Serial.print(",");
Serial.print(data3,3); // 3
Serial.print(",");
Serial.print(data4,3); // 3
Serial.print(",");
Serial.print(data5,3); // 3
Serial.print(",");
Serial.print(data6,3); // 3
Serial.println("}");
}
void Cmd_Unknown()
{
Serial.println(F("I don't understand"));
}
void Cmd_WHCCheckBoxEvent(CommandParameter &Parameters)
{
PUMP_CONTROL_STATE = Parameters.NextParameterAsInteger();
}
void Cmd_BACCheckBoxEvent(CommandParameter &Parameters)
{
BEAM_CONTROL_STATE = Parameters.NextParameterAsInteger();
}
void Cmd_BACZeroStates(CommandParameter &Parameter)
{
int i;
for (i = 0; i < Np; i++)
{
xk_p[i] = 0.0;
}
for (i = 0; i < Nv; i++)
{
xk_v[i] = 0.0;
}
for (i = 0; i < Npf; i++)
{
xk_pf[i] = 0.0;
}
for (i = 0; i < Nbf; i++)
{
xk_bf[i] = 0.0;
}
Serial.println("Feedback Compensator States Zeroed!!!!!!");
}
/*** Core 1 ***/
Metro ISRMetroCore1 = Metro(10); // 60 ms
/* CPU1 Uninitialised Data */
StartOfUninitialised_CPU1_Variables
/* Put your CPU1 fast access variables that have no initial values here e.g. uint32 CPU1_var; */
EndOfUninitialised_CPU1_Variables
/* CPU1 Initialised Data */
StartOfInitialised_CPU1_Variables
const int CORE1HB = 22;
int CORE1HB_flag = 0;
/* Put your CPU1 fast access variables that have an initial value here e.g. uint32 CPU1_var_init = 1; */
// Thermistor parameters
float MAX_V = 5.0; // 3.3 Reference voltage for A2D channels with Due. 5.0 with ShieldBuddy
int MAX_A2D = 1023;
int analogPin0 = 0;
int analogPin1 = 1;
float THETA[3] = {3.33746911687670e+2,-3.83716062783759e+1,5.73463936130444e-2};
float MIN_RESISTANCE = 303.075;
float MAX_RESISTANCE = 367701.4;
float divider_resistance = 10000; // Ohms
int twelve_bit_A2D0_val = 0;
int twelve_bit_A2D1_val = 0;
float water_temperature_right = 0.0;
float water_temperature_left = 0.0;
float water_temperature_average = 0.0;
// Water tank calibration parameters
float m_p2m_right = 0.00122197162098553;
float b_m_right = -0.267221466865174;
float m_p2m_left = 0.00125625961837533;
float b_m_left = -0.273447468867639;
float UFDC_sig_right = 200.0;
float UFDC_sig_left = 200.0;
float water_height_right = 0.0;
float water_height_left = 0.0;
float delta_h1 = 0.0; // right - left
const int UFDC_CS_right = 12; // 12 UFDC CS output (right tank)
const int UFDC_CS_left = 8; // 13 UFDC CS output (left tank)
const unsigned int UFDC_SCK_RATE = 500000; // 100000 /* 100 - 500 kHz */
// D2A MAX541 parameters
const int D2A1_CS = 9; /* D2A chip selects */
const int D2A2_CS = 10;
const float MAX_D2A_voltage = 5.0;
const float MIN_D2A_voltage = 0.0;
const unsigned short MAX_word = 65535; /* 2^16 - 1 = 65535 is maximum unsigned short */
const unsigned int D2A_SCK_RATE = 500000; /* 10MHz, 10000000 */
float input_Vr = 0.4;
float input_Vl = 0.5;
float zero = 0.0;
// A2D AD977 parameters
const int SBBTC = 4; // SBBTC, straight binary or binary twos complement, output (HIGH for SB on pin 8 of AD977)
const int EXTINT = 5; // EXTINT external or internal clock, output (HIGH for external on pin 9 of AD977)
const int RC = 6; // RC, read/convert, output
const int BUSY = 3; // BUSY, input
const int PWRD = 7; // PWRD, power down, output (LOW for powered up on pin 18 of AD977)
const int A2D_CS = 11; // A2D CS, output
const unsigned int A2D_SCK_RATE = 100000; /* 100000 1000000 5MHz */
//const unsigned short MAX_word = 65535; /* 2^16 - 1 = 65535 is maximum unsigned short */
const float MAX_A2D_voltage = 5.0;
// Hallpot calibration parameters
float m_v2deg = 25.2643013874206; // -16.7918701445676;
float b_deg = -59.4501610744572; // 39.1664878889829;
float hallpot_voltage = 0.0;
float theta = 0.0;
EndOfInitialised_CPU1_Variables
float convert_thermistor_voltage2temp(int);
void read_UFDC(float *, int);
void convert_tank_periods2height(float *, float *, float, float, float, float, float, float);
void send_D2A_voltages(float *, float *);
float convert_hallpot_voltage2angle(float, float, float);
float read_A2D_voltage();
SPISettings myD2ASettings(D2A_SCK_RATE, MSBFIRST, SPI_MODE0);
SPISettings myUFDCSettings(UFDC_SCK_RATE, MSBFIRST, SPI_MODE3); // SPI_MODE3
SPISettings myA2DSettings(A2D_SCK_RATE, MSBFIRST, SPI_MODE0); // SPI_MODE0
void setup1() {
pinMode(CORE1HB, OUTPUT);
pinMode (SBBTC, OUTPUT);
pinMode (EXTINT, OUTPUT);
pinMode (RC, OUTPUT);
pinMode (BUSY, INPUT);
pinMode (PWRD, OUTPUT);
pinMode (A2D_CS, OUTPUT);
pinMode (D2A1_CS, OUTPUT);
pinMode (D2A2_CS, OUTPUT);
pinMode(UFDC_CS_right, OUTPUT);
pinMode(UFDC_CS_left, OUTPUT);
digitalWrite(CORE1HB,HIGH); // start out high
digitalWrite(SBBTC,HIGH); // straight binary
digitalWrite(EXTINT,HIGH); // external clock
digitalWrite(RC,HIGH); // start out high
digitalWrite(PWRD,LOW); // powered up
digitalWrite(A2D_CS,HIGH); // start out high
digitalWrite(D2A1_CS,HIGH); // start out high
digitalWrite(D2A2_CS,HIGH); // start out high
digitalWrite(UFDC_CS_right,HIGH); // start out high
digitalWrite(UFDC_CS_left,HIGH); // start out high
send_D2A_voltages(&zero,&zero);
delay(1000);
Serial.begin(115200);
SPI.begin();
}
void loop1() {
if (ISRMetroCore1.check() == 1)
{
twelve_bit_A2D0_val = analogRead(analogPin0); // read the input pin
twelve_bit_A2D1_val = analogRead(analogPin1); // read the input pin
water_temperature_right = convert_thermistor_voltage2temp(twelve_bit_A2D0_val );
water_temperature_left = convert_thermistor_voltage2temp(twelve_bit_A2D1_val);
water_temperature_average = (water_temperature_right + water_temperature_left)/2.0;
//read_UFDC(&UFDC_sig_right,1); // 1 for right, 2 for left (about 7 milliseconds for each read)
//read_UFDC(&UFDC_sig_left,2); // 1 for right, 2 for left
//convert_tank_periods2height(&water_height_right,&water_height_left,UFDC_sig_right,UFDC_sig_left,m_p2m_right,b_m_right,m_p2m_left,b_m_left);
//delta_h1 = water_height_right - water_height_left;
hallpot_voltage = read_A2D_voltage();
//hallpot_voltage = read_A2D_voltage();
theta = convert_hallpot_voltage2angle(hallpot_voltage,m_v2deg,b_deg);
send_D2A_voltages(&input_Vr,&input_Vl);
//Serial.println("water_height_right = \n");
//Serial.println(UFDC_sig_right,DEC);
//Serial.println("water_height_left = \n");
//Serial.println(UFDC_sig_left,DEC);
Serial.println("hallpot_voltage = \n");
Serial.println(hallpot_voltage,DEC);
Serial.println("hallpot angle = \n");
Serial.println(theta,DEC);
Serial.println("\n\n\n");
CORE1HB_flag = !CORE1HB_flag;
digitalWrite(CORE1HB,CORE1HB_flag);
}
}
float convert_thermistor_voltage2temp(int A2D_val)
{
float A2D_voltage = 0.0;
float thermistor_resistance = 0.0;
float thermistor_temperature = 0.0;
A2D_voltage = (MAX_V/MAX_A2D)*(A2D_val);
if(A2D_voltage <= (MAX_V/MAX_A2D)*(1.0))
{
A2D_voltage = (MAX_V/MAX_A2D)*(1.0);
}
thermistor_resistance = divider_resistance*((MAX_V/A2D_voltage) - 1);
if(thermistor_resistance <= MIN_RESISTANCE)
{
thermistor_resistance = MIN_RESISTANCE;
}
thermistor_temperature = THETA[0] + THETA[1]*log(thermistor_resistance) + THETA[2]*(pow(log(thermistor_resistance),3));
return thermistor_temperature;
}
void read_UFDC(float *UFDC_sig, int side)
{
String inString = "";
byte recieved_value = 0;
byte fip_sig[13];
char fip_cup[27];
byte high_bit_mask = 0xF0;
byte low_bit_mask = 0x0F;
int UFDC_CS;
switch(side)
{
case 1 : // right
UFDC_CS = UFDC_CS_right;
break;
case 2: // left
UFDC_CS = UFDC_CS_left;
break;
default:
UFDC_CS = UFDC_CS_right;
}
//SPI.beginTransaction(SPISettings(UFDC_SCK_RATE, MSBFIRST, SPI_MODE3)); // 100 - 500 kHz
SPI.beginTransaction(myUFDCSettings); // 100 - 500 kHz
// Set accuracy 0x02, 09 = 0.001%, 06 = 0.01%
digitalWrite(UFDC_CS,LOW);
recieved_value = SPI.transfer(0x02);
recieved_value = SPI.transfer(0x06);
digitalWrite(UFDC_CS,HIGH);
// Get Signal Measurement ///////////////////////
// Set mode 0x06, TX1 0x01 TX2 0x0F
digitalWrite(UFDC_CS,LOW);
recieved_value = SPI.transfer(0x06);
recieved_value = SPI.transfer(0x01);
digitalWrite(UFDC_CS,HIGH);
// Start measurement
digitalWrite(UFDC_CS,LOW);
recieved_value = SPI.transfer(0x09);
digitalWrite(UFDC_CS,HIGH);
// Check measurement status
recieved_value = 0x01; // 0x01
while(recieved_value != 0x00)
{
digitalWrite(UFDC_CS,LOW);
recieved_value = SPI.transfer(0x03);
recieved_value = SPI.transfer(0xFF);
recieved_value = SPI.transfer(0xFF);
digitalWrite(UFDC_CS,HIGH);
}
// Get measurement!
digitalWrite(UFDC_CS,LOW);
recieved_value = SPI.transfer(0x07); // Get measurement, 07 is R1 (BCD), 08 is R2 (BINARY)
recieved_value = SPI.transfer(0xFF);
fip_sig[0] = SPI.transfer(0xFF);
fip_sig[1] = SPI.transfer(0xFF);
fip_sig[2] = SPI.transfer(0xFF);
fip_sig[3] = SPI.transfer(0xFF);
fip_sig[4] = SPI.transfer(0xFF);
fip_sig[5] = SPI.transfer(0xFF);
fip_sig[6] = SPI.transfer(0xFF);
fip_sig[7] = SPI.transfer(0xFF);
fip_sig[8] = SPI.transfer(0xFF);
fip_sig[9] = SPI.transfer(0xFF);
fip_sig[10] = SPI.transfer(0xFF);
fip_sig[11] = SPI.transfer(0xFF);
fip_sig[12] = SPI.transfer(0xFF);
digitalWrite(UFDC_CS,HIGH);
SPI.endTransaction();
fip_cup[0] = (char) fip_sig[0];
fip_cup[1] = (char) (0x30 | (high_bit_mask & fip_sig[1]) >> 4); // high and low nibble ip5
fip_cup[2] = (char) (0x30 | low_bit_mask & fip_sig[1]);
fip_cup[3] = (char) (0x30 | (high_bit_mask & fip_sig[2]) >> 4);
fip_cup[4] = (char) (0x30 | low_bit_mask & fip_sig[2]);
fip_cup[5] = (char) (0x30 | (high_bit_mask & fip_sig[3]) >> 4);
fip_cup[6] = (char) (0x30 | low_bit_mask & fip_sig[3]);
fip_cup[7] = (char) (0x30 | (high_bit_mask & fip_sig[4]) >> 4);
fip_cup[8] = (char) (0x30 | low_bit_mask & fip_sig[4]);
fip_cup[9] = (char) (0x30 | (high_bit_mask & fip_sig[5]) >> 4);
fip_cup[10] = (char) (0x30 | low_bit_mask & fip_sig[5]);
fip_cup[11] = (char) (0x30 | (high_bit_mask & fip_sig[6]) >> 4);
fip_cup[12] = (char) (0x30 | low_bit_mask & fip_sig[6]);
strcpy(&fip_cup[13],".");
fip_cup[14] = (char) (0x30 | (high_bit_mask & fip_sig[7]) >> 4); // high and low nibble fp0
fip_cup[15] = (char) (0x30 | low_bit_mask & fip_sig[7]);
fip_cup[16] = (char) (0x30 | (high_bit_mask & fip_sig[8]) >> 4);
fip_cup[17] = (char) (0x30 | low_bit_mask & fip_sig[8]);
fip_cup[18] = (char) (0x30 | (high_bit_mask & fip_sig[9]) >> 4);
fip_cup[19] = (char) (0x30 | low_bit_mask & fip_sig[9]);
fip_cup[20] = (char) (0x30 | (high_bit_mask & fip_sig[10]) >> 4);
fip_cup[21] = (char) (0x30 | low_bit_mask & fip_sig[10]);
fip_cup[22] = (char) (0x30 | (high_bit_mask & fip_sig[11]) >> 4);
fip_cup[23] = (char) (0x30 | low_bit_mask & fip_sig[11]);
fip_cup[24] = (char) (0x30 | (high_bit_mask & fip_sig[12]) >> 4);
fip_cup[25] = (char) (0x30 | low_bit_mask & fip_sig[12]);
strcpy(&fip_cup[26],"\0");
inString = String(fip_cup);
*UFDC_sig = inString.toFloat();
inString = "";
}
void convert_tank_periods2height(float *whr, float *whl, float periodr, float periodl, float mr, float br, float ml, float bl)
{
*whr = mr*periodr + br; // meters
*whl = ml*periodl + bl; // meters
}
float read_A2D_voltage()
{
byte recieved_val_high_byte = 0;
byte recieved_val_low_byte = 0;
byte recieved_val_notused_byte = 0;
unsigned short recieved_val = 0;
float voltage = 0.0;
int BUSY_val = 0;
//SPI.beginTransaction(SPISettings(A2D_SCK_RATE, MSBFIRST, SPI_MODE0)); // SPI_MODE0 15150000
SPI.beginTransaction(myA2DSettings); // SPI_MODE0 15150000
digitalWrite(A2D_CS,LOW);
digitalWrite(RC,LOW);
delayMicroseconds(2);
digitalWrite(RC,HIGH);
while(!BUSY_val){
BUSY_val = digitalRead(BUSY); /* BUSY is active when low */
}
recieved_val_high_byte = SPI.transfer(0xFF);
recieved_val_low_byte = SPI.transfer(0xFF);
recieved_val_notused_byte = SPI.transfer(0xFF);
digitalWrite(A2D_CS,HIGH);
SPI.endTransaction();
Serial.println("recieved_val_high_byte = \n");
Serial.println(recieved_val_high_byte,BIN);
Serial.println("recieved_val_high_byte (unsigned short) = \n");
Serial.println((unsigned short) recieved_val_high_byte,BIN);
Serial.println("recieved_val_high_byte (((unsigned short) recieved_val_high_byte) << 8) = \n");
Serial.println((((unsigned short) recieved_val_high_byte) << 8),BIN);
Serial.println("recieved_val_low_byte = \n");
Serial.println(recieved_val_low_byte,BIN);
Serial.println("recieved_val_low_byte (unsigned short) = \n");
Serial.println((unsigned short) recieved_val_low_byte,BIN);
recieved_val = ( (((unsigned short) recieved_val_high_byte) << 8) | ((unsigned short) recieved_val_low_byte) );
Serial.println("recieved_val = \n");
Serial.println(recieved_val,BIN);
Serial.println(recieved_val,DEC);
Serial.println(MAX_word,DEC);
voltage = (float) recieved_val*(MAX_A2D_voltage/MAX_word);
return voltage;
}
float convert_hallpot_voltage2angle(float V_in, float m, float b)
{
float angle = 0.0;
angle = m*V_in + b; // degrees
return angle;
}
/*** Core 2 ***/
Metro ISRMetroCore2 = Metro(6); // 60 ms
/* CPU2 Uninitialised Data */
StartOfUninitialised_CPU2_Variables
/* Put your CPU2 fast access variables that have no initial values here e.g. uint32 CPU2_var; */
EndOfUninitialised_CPU2_Variables
/* CPU2 Initialised Data */
StartOfInitialised_CPU2_Variables
const int CORE2HB = 26;
int CORE2HB_flag = 0;
/* Put your CPU2 fast access variables that have an initial value here e.g. uint32 CPU2_var_init = 1; */
// D2A MAX541 parameters
//const int D2A1_CS = 9; /* D2A chip selects */
//const int D2A2_CS = 10;
//const float MAX_D2A_voltage = 5.0;
//const float MIN_D2A_voltage = 0.0;
//const unsigned short MAX_word = 65535; /* 2^16 - 1 = 65535 is maximum unsigned short */
//const unsigned int D2A_SCK_RATE = 10000000; /* 10MHz */
//float input_Vr = 2.0;
//float input_Vl = 3.0;
EndOfInitialised_CPU2_Variables
//void send_D2A_voltages(float *, float *);
//SPISettings myD2ASettings(D2A_SCK_RATE, MSBFIRST, SPI_MODE0);
void setup2() {
pinMode(CORE2HB, OUTPUT);
digitalWrite(CORE2HB,HIGH); // start out high
// put your setup code for core 2 here, to run once:
// pinMode (D2A1_CS, OUTPUT);
// pinMode (D2A2_CS, OUTPUT);
//
// digitalWrite(D2A1_CS,HIGH); // start out high
// digitalWrite(D2A2_CS,HIGH); // start out high
}
void loop2() {
if (ISRMetroCore2.check() == 1)
{
//send_D2A_voltages(&input_Vr,&input_Vl); // control + idle voltages
CORE2HB_flag = !CORE2HB_flag;
digitalWrite(CORE2HB,CORE2HB_flag);
}
}
void send_D2A_voltages(float *V_D2A1, float *V_D2A2)
{
unsigned short data1 = 0, data2 = 0; /* For Due short is 16 bits, int is 32 bits */
byte data1_highbyte, data1_lowbyte;
byte data2_highbyte, data2_lowbyte;
if (*V_D2A1 < MIN_D2A_voltage)
{
*V_D2A1 = MIN_D2A_voltage;
}
if (*V_D2A1 > MAX_D2A_voltage)
{
*V_D2A1 = MAX_D2A_voltage;
}
if (*V_D2A2 < MIN_D2A_voltage)
{
*V_D2A2 = MIN_D2A_voltage;
}
if (*V_D2A2 > MAX_D2A_voltage)
{
*V_D2A2 = MAX_D2A_voltage;
}
data1 = (unsigned short) (MAX_word/MAX_D2A_voltage)*(*V_D2A1);
data2 = (unsigned short) (MAX_word/MAX_D2A_voltage)*(*V_D2A2);
data1_highbyte = (byte) ((data1 & 0xFF00) >> 8);
data1_lowbyte = (byte) (data1 & 0x00FF);
data2_highbyte = (byte) ((data2 & 0xFF00) >> 8);
data2_lowbyte = (byte) (data2 & 0x00FF);
//SPI.beginTransaction(SPISettings(D2A_SCK_RATE, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(myD2ASettings);
digitalWrite(D2A1_CS,LOW);
SPI.transfer(data1_highbyte);
SPI.transfer(data1_lowbyte);
digitalWrite(D2A1_CS,HIGH);
SPI.endTransaction();
//SPI.beginTransaction(SPISettings(D2A_SCK_RATE, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(myD2ASettings);
digitalWrite(D2A2_CS,LOW);
SPI.transfer(data2_highbyte);
SPI.transfer(data2_lowbyte);
digitalWrite(D2A2_CS,HIGH);
SPI.endTransaction();
}