Skip to content

Instantly share code, notes, and snippets.

@stephanschulz
Last active November 19, 2019 21:54
Show Gist options
  • Select an option

  • Save stephanschulz/c2702d78ab67b0ef1613d9ab1d23947e to your computer and use it in GitHub Desktop.

Select an option

Save stephanschulz/c2702d78ab67b0ef1613d9ab1d23947e to your computer and use it in GitHub Desktop.
#include <Arduino.h>
#include <SPI.h>
#define CLOCK_SPEED 2'000'000 // 2.5 MHz SSI Clock
#define CS_PIN 10
#define SCK_PIN 13 // SSI CLK line
#define SCK_PIN_13_INDEX 0
//#define SCK_PIN_14_INDEX 1
//#define SCK_PIN_27_INDEX 2
SPISettings settingsA(CLOCK_SPEED, MSBFIRST, SPI_MODE1);
uint8_t encoderBuf[4] = {0, 0, 0, 0};
void makeTransfer();
uint16_t decodeEncoderFrame();
void calculateAndPrintPosition(uint16_t& encoderData);
void setup()
{
SerialUSB.begin(9600);
SPI.begin(); // SPI.begin() will initialize the SPI port, as well as CLK pin
pinMode(CS_PIN, OUTPUT);
pinMode(SCK_PIN, OUTPUT); // pinMode() will initialize the CLK pin as output (SPI port can't use it now!)
digitalWriteFast(SCK_PIN, HIGH); // Set CLK line HIGH (to meet the requirements of SSI interface)
// digitalWriteFast(CS_PIN, LOW);
while (!SerialUSB) {}
SerialUSB.println("Started!");
}
void loop()
{
makeTransfer();
uint16_t encoderData = decodeEncoderFrame();
calculateAndPrintPosition(encoderData);
delay(200);
}
void makeTransfer()
{
digitalWrite(CS_PIN, HIGH);
digitalWrite(CS_PIN, LOW);
digitalWriteFast(SCK_PIN, HIGH);
digitalWriteFast(SCK_PIN, LOW); // Set CLK line LOW (to inform encoder -> latch data)
delayMicroseconds(1); // Running above 500kHz perform Delay First Clock function
// Before in setup() the pinMode() change the CLK pin function to output,
// now we have to enable usage of this pin by SPI port with calling SPI.begin():
// SPI.begin();
// Or use this one below - a bit faster but SPI port and SCK pin dependent option. I belive there is a more elegant and more
// scalable solution, maybe even supported by hardware for this purpose? - if anyone can point me it out I would be grateful:
uint8_t pinIndex = SCK_PIN_13_INDEX;
volatile uint32_t* reg = portConfigRegister(SPIClass::spi0_hardware.sck_pin[pinIndex]);
*reg = SPIClass::spi0_hardware.sck_mux[pinIndex];
SPI.beginTransaction(settingsA); // We use transactional API
for (int i = 0; i < 2; i++)
{
encoderBuf[i] = SPI.transfer(0xAA); // Transfer anything and read data back
Serial.print(i);
Serial.print(" i ");
Serial.print((int)encoderBuf[i]);
Serial.println();
}
SPI.endTransaction(); // We use transactional API
pinMode(SCK_PIN, OUTPUT); // A while before we set CLK pin to be used by SPI port, now we have to change it manually...
digitalWriteFast(SCK_PIN, LOW);
digitalWriteFast(SCK_PIN, HIGH); // ... back to idle HIGH
}
uint16_t decodeEncoderFrame()
{
// uint32_t data = static_cast<uint32_t>(encoderBuf[0] << 24) |
// static_cast<uint32_t>(encoderBuf[1] << 16) |
// static_cast<uint32_t>(encoderBuf[2] << 8) |
// static_cast<uint32_t>(encoderBuf[3]); // here transfer8 was made
uint16_t data = static_cast<uint16_t>(encoderBuf[0] << 8) |
static_cast<uint16_t>(encoderBuf[1]); // here transfer8 was made
Serial.println("data ");
Serial.print(data);
Serial.println();
data = data >> 6; // shift right to cut status and parity bits only 'position data' is in data variable now!
return data;
}
void calculateAndPrintPosition(uint16_t& encoderData)
{
// encoderPosition is placed in front (starting from MSB of uint32_t) so shift it for 11 bits to align position data right
// no shifting needed (we done it in decodeEncoderFrame())
// int16_t encoderPosition = (encoderData >> 9);
// you have 10 bits position data so max is 1 << 10 not 1 << 20 as in my case
//float angularAbsolutePosition = static_cast<float>(encoderPosition) / static_cast<float>(1 << 20) * 360.0F;
float angularAbsolutePosition = static_cast<float>(encoderData) / static_cast<float>(1 << 10) * 360.0F;
SerialUSB.println("Encoder Positon = " + String(encoderData) + " Angle = " + String(angularAbsolutePosition, 4));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment