#include <Wire.h>
#include <Adafruit_MCP4725.h>
#include <SPI.h>
#define kNOERROR 0
#define kPRIMARYREADERROR 1
#define kEXTENDEDREADTIMEOUTERROR 2
#define kPRIMARYWRITEERROR 3
#define kEXTENDEDWRITETIMEOUTERROR 4
#define kCRCERROR 5
#define kUNABLETOCHANGEPROCESSORSTATE 6
//190907const uint16_t LEDPin = 13;
const uint32_t WRITE = 0x40;
const uint32_t READ = 0x00;
const uint32_t COMMAND_MASK = 0xC0;
const uint32_t ADDRESS_MASK = 0x3F;
unsigned long nextTime;
bool ledOn = false;
bool includeCRC = true;
uint16_t angle;
uint16_t temperature;
uint16_t fieldStrength;
float angleDegrees;
float temperatureC;
float fieldStrengthGauss;
const int sensorPin = A1; // select the input pin for the input voltage
float sensorVoltage = 0;
float outputVoltage = 0;
Adafruit_MCP4725 dac;
//Code below is to read Vin, which will be used later as the "reference voltage" for the DAC
long readVcc() {
// Read 1.1V reference against AVcc
// set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
//#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0) ;
#else
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Start conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both
long result = (high<<8) | low;
result = 1105300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
return result; // Vcc in millivolts
}
void setup(void) {
Serial.begin(115200);
while (!Serial);
Serial.println("Hello!");
uint16_t unused;
uint32_t flags;
uint16_t angle;
uint32_t flagsAndZeroOffset;
// Initialize SPI
SPI.begin();
pinMode(SS, OUTPUT);
//Sets Unused Pins to Internal Pullup
pinMode(2,INPUT_PULLUP);
pinMode(3,INPUT_PULLUP);
pinMode(4,INPUT_PULLUP);
pinMode(5,INPUT_PULLUP);
pinMode(6,INPUT_PULLUP);
pinMode(7,INPUT_PULLUP);
pinMode(8,INPUT_PULLUP);
pinMode(9,INPUT_PULLUP);
pinMode(15,INPUT_PULLUP);
pinMode(16,INPUT_PULLUP);
pinMode(17,INPUT_PULLUP);
//190907 pinMode(LEDPin, OUTPUT);
nextTime = millis();
//190907digitalWrite(LEDPin, LOW);
digitalWrite(SS, HIGH);
// Make sure all of the SPI pins are
// ready by doing a read
PrimaryRead(SS, 0x0, unused);
// Unlock the device
ExtendedWrite(SS, 0xFFFE, 0x27811F77);
// Make sure the device is unlocked
ExtendedRead(SS, 0x22, flags);
if (!((flags & 0x0022) == 0x0020))
{
Serial.println("Device is not Unlocked");
}
// For Adafruit MCP4725A1 the address is 0x62 (default) or 0x63 (ADDR pin tied to VCC)
dac.begin(0x62);
TWBR = ((F_CPU /400000l) - 16) / 2; // Change the i2c clock to 400KHz
}
void loop(void) {
if (PrimaryRead(SS, 0x20, angle) == kNOERROR)
{
angleDegrees = (float)(angle & 0x0FFF) * (360.0 / 4096.0);
if (CalculateParity(angle))
{
// Serial.print("Angle = ");
// Serial.print(angleDegrees);
// Serial.println(" Degrees");
}
else
{
// Serial.println("Parity error on Angle read");
}
}
else
{
// Serial.println("Unable to read Angle");
}
// This is the lookup table I use to tell the DAC how much voltage to output
// Angle From Sensor on left // Corresponding Desired Output Voltage on right
float array[8] = {
0, 3267,
29, 4785,
287, 265,
360, 3267,
};
if (angleDegrees<= array[0])
{
outputVoltage = dac.setNearestActualVoltage(array[1], sensorVoltage, false);
// Serial.println("Your below the bottom end of the table");
}
else if (angleDegrees >= array[6])
{
outputVoltage = dac.setNearestActualVoltage(sensorVoltage, sensorVoltage, false);
// Serial.println("Your above the top end of the table");
}
int x;
for (x= 0; x<8; x=x+2){
if (angleDegrees >=array[x]
&& angleDegrees <=array[x+2])
outputVoltage = dac.setNearestActualVoltage((array[x+1] + ( (array[x+3] - array[x+1]) * ( (angleDegrees - array[x]
) / (array[x+2] - array[x]
) ) )),sensorVoltage, false);
}
//Serial.println("The Output Voltage is: ");
//Serial.println(outputVoltage);
}
uint16_t PrimaryRead(uint16_t cs, uint16_t address, uint16_t& value)
{
uint16_t command;
if (!includeCRC)
{
uint8_t crcValue;
uint8_t crcCommand;
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3));
// Combine the register address and the command into one byte
command = ((address & ADDRESS_MASK) | READ) << 8;
crcCommand = CalculateCRC(command);
// take the chip select low to select the device
PORTB &= ~_BV(PB2);
// send the device the register you want to read
SPI.transfer16(command);
SPI.transfer(crcCommand);
PORTB |= _BV(PB2);
PORTB &= ~_BV(PB2);
// send the command again to read the contents
value = SPI.transfer16(command);
crcValue = SPI.transfer(crcCommand);
// take the chip select high to de-select
PORTB |= _BV(PB2);
// Restore the 8 bit description
SPI.endTransaction();
// Check the CRC value
if (CalculateCRC(value) != crcValue)
{
//Serial.println("Calculated CRC = ");
//Serial.println(+ CalculateCRC(value));
//Serial.println("crcValue = ");
//Serial.println(crcValue);
return kCRCERROR;
}
}
else
{
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3));
// Combine the register address and the command into one byte
command = ((address & ADDRESS_MASK) | READ) << 8;
// take the chip select low to select the device
PORTB &= ~_BV(PB2);
// send the device the register you want to read
SPI.transfer16(command);
PORTB |= _BV(PB2);
PORTB &= ~_BV(PB2);
// send the command again to read the contents
value = SPI.transfer16(command);
// take the chip select high to de-select
PORTB |= _BV(PB2);
SPI.endTransaction();
}
return kNOERROR;
}
/*
* PrimaryRead
*
* Read from the primary serial registers
*/
void PrimaryRead(uint16_t cs, uint16_t* addresses, uint16_t* values, uint16_t* errors, uint16_t numberOfItems)
{
uint16_t command;
if (includeCRC)
{
uint8_t crcValue;
uint8_t crcCommand;
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3));
// to send 4 bits
// Combine the register address and the command into one byte
command = ((addresses[0] & ADDRESS_MASK) | READ) << 8;
crcCommand = CalculateCRC(command);
// take the chip select low to select the device
PORTB &= ~_BV(PB2);
// send the device the register you want to read
SPI.transfer16(command);
SPI.transfer(crcCommand);
PORTB |= _BV(PB2);
for (int index = 0; index < (numberOfItems - 1); ++index)
{
// Combine the register address and the command into one byte
command = ((addresses[index + 1] & ADDRESS_MASK) | READ) << 8;
crcCommand = CalculateCRC(command);
PORTB &= ~_BV(PB2);
// send the command again to read the contents
values[index] = SPI.transfer16(command);
crcValue = SPI.transfer(crcCommand);
// take the chip select high to de-select
PORTB |= _BV(PB2);
// Check the CRC of the read value
if (CalculateCRC(values[index]) != crcValue)
{
errors[index] = kCRCERROR;
}
else
{
errors[index] = kNOERROR;
}
}
PORTB &= ~_BV(PB2);
// send the command again to read the contents
values[numberOfItems - 1] = SPI.transfer16(command);
crcValue = SPI.transfer(crcCommand);
// take the chip select high to de-select
PORTB |= _BV(PB2);
// Check the CRC value
if (CalculateCRC(values[numberOfItems - 1]) != crcValue)
{
errors[numberOfItems - 1] = kCRCERROR;
}
else
{
errors[numberOfItems - 1] = kNOERROR;
}
// Restore the 8 bit description