MSP430F2418: Unable to set P2.3 pin to high - c++

I am using MSO430F2418 for my project. I am sending Hello world message to Bluetooth module via UART pins. Also I need to set pin P2.3 to high to reset the Bluetooth. Unfortunately Im unable to set that perticuler pin to high. When I check the voltage at Reset pin of Bluetooth it is low.
You can see below two lines in my code. I have used these statements to set the P2.3.
P2DIR|=0x08;
P2OUT|=0x08;
I have attached an image. There you can see the hardware. enter image description here
#include <stdio.h>
#include <msp430.h>
const char string[] = { "Hello World\r\n" };
unsigned int i;
int main(void){
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
if (CALBC1_1MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ; // Set DCO
DCOCTL = CALDCO_1MHZ;
P2DIR|=0x08;
P2OUT|=0x08;
P3SEL = 0x30; // P3.4,5 = USCI_A0 TXD/RXD
UCA0CTL1 |= UCSSEL_3; // SMCLK
UCA0BR0 = 8; // 1MHz 115200
UCA0BR1 = 0; // 1MHz 115200
UCA0MCTL = UCBRS2 + UCBRS1; // Modulation UCBRSx = 5
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
// IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
IE2 |= UCA0TXIE;
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0, interrupts enabled
}
#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void)
{
UCA0TXBUF = string[i++]; // TX next character
if (i == sizeof string - 1){ // TX over?
IE2 &= ~UCA0TXIE; // Disable USCI_A0 TX interrupt
_delay_cycles(1000000);
i = 0;
IE2 |= UCA0TXIE; // Enable USCI_A0 TX interrupt
}
}

Related

After configuring SPI communication for SAMD51 enable function freezes the setup

I am currently working to configurate SPI communication in a SAMD51 board. After a lot of research I could find how to setup the registers to start the pin configuration and clock setup, among other things. But there is one procedure in the end of the setup that requires to enable the pin again.
Here is the datasheet for the MCU https://www.mouser.com/datasheet/2/268/60001507A-1130176.pdf
SERCOM4->SPI.CTRLA.bit.ENABLE = 1;
After I call this line the library freezes and I cannot get any other response.
find bellow the cpp file.
#include "SercomSPISlave.h"
// Constructors //
SercomSPISlave::SercomSPISlave()
{
}
// Public Methods //
void SercomSPISlave::Sercom4init()
{
//Setting up NVIC
NVIC_EnableIRQ(SERCOM4_0_IRQn);
NVIC_SetPriority(SERCOM4_0_IRQn,2);
//MCLK->APBDMASK.reg |= MCLK_APBDMASK_SERCOM4;
MCLK->APBDMASK.bit.SERCOM4_ = 1;
//Setting Generic Clock Controller!!!!
//GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCM_SERCOM4_CORE) | //Generic Clock 0
// GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is the source
// GCLK_CLKCTRL_CLKEN; // Enable Generic Clock Generator
GCLK->PCHCTRL[34].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN;
//while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); //Wait for synchronisation
//Configure SERCOM4 SPI PINS
//Set PA12 as input (MOSI) - on D22 / MISO
//Set PB09 as input (SCK) - on A2
//Set PB10 as input (SS) - on D23 / MOSI
//Set PB11 as output (MISO) - on D24 / SCK
PORT->Group[PORTB].PINCFG[11].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM4 SPI PB11
PORT->Group[PORTB].PMUX[11 >> 1].bit.PMUXO = 0x3; //SERCOM 4 is selected for peripheral use of this pad (0x3 selects peripheral function D: SERCOM-ALT)
PORT->Group[PORTB].PINCFG[12].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM4 SPI PB12
PORT->Group[PORTB].PMUX[12 >> 1].bit.PMUXE = 0x3; //SERCOM 4 is selected for peripheral use of this pad (0x3 selects peripheral function D: SERCOM-ALT)
PORT->Group[PORTB].PINCFG[13].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM4 SPI PB13
PORT->Group[PORTB].PMUX[13 >> 1].bit.PMUXO = 0x3; //SERCOM 4 is selected for peripheral use of this pad (0x3 selects peripheral function D: SERCOM-ALT)
PORT->Group[PORTA].PINCFG[9].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM4 SPI PB09
PORT->Group[PORTA].PMUX[9 >> 1].bit.PMUXO = 0x3; //SERCOM 4 is selected for peripheral use of this pad (0x3 selects peripheral function D: SERCOM-ALT)
/*
Explanation:
PMUXEN stands for Peripheral Multiplexing Enable
PMUXE stands for Even bits in the Peripheral Multiplexing register
PMUXO stands for Odd bits in the Peripheral Multiplexing register
The selection of peripheral function A to H is done by writing to the Peripheral Multiplexing Odd and Even bits in the Peripheral Multiplexing register (PMUXn.PMUXE/O) in the PORT.
Reference: Atmel-42181G-SAM-D21_Datasheet section 6.1 on page 21
PA12 corresponds to: PORTA, PMUX[6] Even
PB09 corresponds to: PORTB, PMUX[4] Odd
PB10 corresponds to: PORTB, PMUX[5] Even
PB11 corresponds to: PORTB, PMUX[5] Odd
In general:
Px(2n+0/1) corresponds to Portx, PMUX[n] Even=0/Odd=1*/
//Disable SPI 1
SERCOM4->SPI.CTRLA.bit.ENABLE =0;
while(SERCOM4->SPI.SYNCBUSY.bit.ENABLE);
//Reset SPI 1
SERCOM4->SPI.CTRLA.bit.SWRST = 1;
while(SERCOM4->SPI.CTRLA.bit.SWRST || SERCOM4->SPI.SYNCBUSY.bit.SWRST);
//Set up SPI Control A Register
SERCOM4->SPI.CTRLA.bit.DORD = 0; //MSB first
SERCOM4->SPI.CTRLA.bit.CPOL = 0; //SCK is low when idle, leading edge is rising edge
SERCOM4->SPI.CTRLA.bit.CPHA = 0; //data sampled on leading sck edge and changed on a trailing sck edge
SERCOM4->SPI.CTRLA.bit.FORM = 0x0; //Frame format = SPI
SERCOM4->SPI.CTRLA.bit.DIPO = 0x0; //DATA PAD0 MOSI is used as slave input (slave mode) // page 492
SERCOM4->SPI.CTRLA.bit.DOPO = 0x2; //DATA PAD2 MISO is used as slave output
SERCOM4->SPI.CTRLA.bit.MODE = 0x2; //SPI in Slave mode
SERCOM4->SPI.CTRLA.bit.IBON = 0x1; //Buffer Overflow notification
SERCOM4->SPI.CTRLA.bit.RUNSTDBY = 1; //wake on receiver complete
//Set up SPI control B register
//SERCOM4->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver
SERCOM4->SPI.CTRLB.bit.SSDE = 0x1; //Slave Selecte Detection Enabled
SERCOM4->SPI.CTRLB.bit.CHSIZE = 0; //character size 8 Bit
//SERCOM4->SPI.CTRLB.bit.PLOADEN = 0x1; //Enable Preload Data Register
//while (SERCOM4->SPI.SYNCBUSY.bit.CTRLB);
//Set up SPI interrupts
SERCOM4->SPI.INTENSET.bit.SSL = 0x1; //Enable Slave Select low interrupt
SERCOM4->SPI.INTENSET.bit.RXC = 0x1; //Receive complete interrupt
SERCOM4->SPI.INTENSET.bit.TXC = 0x1; //Receive complete interrupt
SERCOM4->SPI.INTENSET.bit.ERROR = 0x1; //Receive complete interrupt
SERCOM4->SPI.INTENSET.bit.DRE = 0x1; //Data Register Empty interrupt
//init SPI CLK
//SERCOM4->SPI.BAUD.reg = SERCOM_FREQ_REF / (2*4000000u)-1;
//Enable SPI
SERCOM4->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver, this is done here due to errate issue
while(SERCOM4->SPI.SYNCBUSY.bit.CTRLB); //wait until receiver is enabled
Serial.begin(115200);
SERCOM4->SPI.CTRLA.bit.ENABLE = 1;
Serial.print(SERCOM4->SPI.CTRLA.bit.ENABLE);
while(SERCOM4->SPI.SYNCBUSY.bit.ENABLE);
}
Find bellow the .h file.
#ifndef SercomSPISlave_h
#define SercomSPISlave_h
#include <Arduino.h>
class SercomSPISlave
{
public:
// Constructors //
SercomSPISlave();
// Public Methods //
void Sercom4init();
};
#endif
Find bellow the .ino code
#include <SercomSPISlave.h>
SercomSPISlave SPISlave;
void setup()
{
Serial.begin(115200);
Serial.println("Serial started");
SPISlave.Sercom4init();
while(!Serial);
Serial.println("Sercom1 SPI slave initialized!");
}
void loop()
{
}
I appreciate any support you can give me.

How do I port C++ code to Esp8266 and Esp32 using interrupts from code written for older boards

I am trying to port some C++ Arduino code to more recent ESP8266 and ESP32 boards.
I have checked already the Arduino Stack Exchange forum unfortunately without results
Porting this C++ code from older Arduino to Esp8266/Esp32 does not work, I have added also the compiling errors at the bottom of this question:
/* rcTiming.ino -- JW, 30 November 2015 --
* Uses pin-change interrupts on A0-A4 to time RC pulses
*
* Ref: https://arduino.stackexchange.com/questions/18183/read-rc-receiver-channels-using-interrupt-instead-of-pulsein
*
*/
#include <Streaming.h>
static byte rcOld; // Prev. states of inputs
volatile unsigned long rcRises[4]; // times of prev. rising edges
volatile unsigned long rcTimes[4]; // recent pulse lengths
volatile unsigned int rcChange=0; // Change-counter
// Be sure to call setup_rcTiming() from setup()
void setup_rcTiming() {
rcOld = 0;
pinMode(A0, INPUT); // pin 14, A0, PC0, for pin-change interrupt
pinMode(A1, INPUT); // pin 15, A1, PC1, for pin-change interrupt
pinMode(A2, INPUT);
pinMode(A3, INPUT);
PCMSK1 |= 0x0F; // Four-bit mask for four channels
PCIFR |= 0x02; // clear pin-change interrupts if any
PCICR |= 0x02; // enable pin-change interrupts
}
// Define the service routine for PCI vector 1
ISR(PCINT1_vect) {
byte rcNew = PINC & 15; // Get low 4 bits, A0-A3
byte changes = rcNew^rcOld; // Notice changed bits
byte channel = 0;
unsigned long now = micros(); // micros() is ok in int routine
while (changes) {
if ((changes & 1)) { // Did current channel change?
if ((rcNew & (1<<channel))) { // Check rising edge
rcRises[channel] = now; // Is rising edge
} else { // Is falling edge
rcTimes[channel] = now-rcRises[channel];
}
}
changes >>= 1; // shift out the done bit
++channel;
++rcChange;
}
rcOld = rcNew; // Save new state
}
void setup() {
Serial.begin(115200);
Serial.println("Starting RC Timing Test");
setup_rcTiming();
}
void loop() {
unsigned long rcT[4]; // copy of recent pulse lengths
unsigned int rcN;
if (rcChange) {
// Data is subject to races if interrupted, so off interrupts
cli(); // Disable interrupts
rcN = rcChange;
rcChange = 0; // Zero the change counter
rcT[0] = rcTimes[0];
rcT[1] = rcTimes[1];
rcT[2] = rcTimes[2];
rcT[3] = rcTimes[3];
sei(); // reenable interrupts
Serial << "t=" << millis() << " " << rcT[0] << " " << rcT[1]
<< " " << rcT[2] << " " << rcT[3] << " " << rcN << endl;
}
sei(); // reenable interrupts
}
The compiling error is:
expected constructor, destructor, or type conversion before '(' token
at line:
ISR(PCINT1_vect) {
I am seeking suggestions to get it working thank you.
All ESP32 GPIO pins are interrupt-capable pins.
You can use interrupts, but in a different way.
attachInterrupt(GPIOPin, ISR, Mode);
Mode – Defines when the interrupt should be triggered. Five constants are predefined as valid values:HIGH, LOW, CHANGE, RISING, FALLING
void IRAM_ATTR ISR() {
Statements;
}
Interrupt service routines should have the IRAM_ATTR attribute, according to the ESP32 documentation

Arduino .read() function interfering with BLE connection

Firstly, I want to apologize as I am new to BLE connectivity and much of Arduino programming. I am busy with a project which in involved making a smart coffee scale which can output data to a smartphone via a BLE connection. I am working with an Arduino nano 33 IoT, and an hx711 load cell amplifier.
I need to create a program where I can send and receive data to and from the Arduino to the smartphone app. I have used standard ArduinoBLE peripheral libraries such as the "BatteryMonitor" sketch and the "ButtonLED" sketch. By combining both of these example sketches together I have managed to established a connection where I can send and receive data.
The problem arises when I try to use functions within the HX711 library such as scale.read(); to retrieve values being output from the hx711 amplifier. When I use a serial read function such as scale.read() the bluetooth connection fails before establishing itself properly. I imagine this is due to the scale.read() function interfering with the serial data being transmitted and received by the Arduino, but I have no clue how to get around this problem.
I basically want to change the battery monitor output to be the output of the value read from the hx711 load cell amplifier but I am struggling to get this to work.
#include "HX711.h"
#include <ArduinoBLE.h>
HX711 scale;
BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // BLE LED Service
// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEByteCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
BLEUnsignedCharCharacteristic batteryLevelChar("2A19", // standard 16-bit characteristic UUID
BLERead | BLENotify); // remote clients will be able to get notifications if this characteristic changes
int oldBatteryLevel = 0; // last battery level reading from analog input
long previousMillis = 0; // last time the battery level was checked, in ms
const int ledPin = LED_BUILTIN; // pin to use for the LED
double val;
void setup() {
Serial.begin(9600);
scale.begin(A1, A0); //Initialized scale on these pins
while (!Serial);
scale.set_scale(432.f); // this value is obtained by calibrating the scale with known weights; see the README for details
scale.tare(); // reset the scale to 0
// set LED pin to output mode
pinMode(ledPin, OUTPUT);
// begin initialization
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (1);
}
// set advertised local name and service UUID:
BLE.setLocalName("COFFEE");
BLE.setAdvertisedService(ledService);
// add the characteristic to the service
ledService.addCharacteristic(switchCharacteristic);
ledService.addCharacteristic(batteryLevelChar); // add the battery level characteristic
// add service
BLE.addService(ledService);
// set the initial value for the characeristic:
switchCharacteristic.writeValue(0);
// start advertising
BLE.advertise();
Serial.println("BLE LED Peripheral");
}
void loop()
{
// listen for BLE peripherals to connect:
BLEDevice central = BLE.central();
// if a central is connected to peripheral:
if (central) {
Serial.print("Connected to central: ");
// print the central's MAC address:
Serial.println(central.address());
// while the central is still connected to peripheral:
while (central.connected())
{
// Battery Monitor
// scale.read();
long currentMillis = millis();
// if 200ms have passed, check the battery level:
if (currentMillis - previousMillis >= 200) {
previousMillis = currentMillis;
// scale.read(); // This function alone will prevent the BLE connection from establishing properly.
updateBatteryLevel();
// outputScale();
}
// if the remote device wrote to the characteristic,
// use the value to control the LED:
if (switchCharacteristic.written()) {
if (switchCharacteristic.value()) { // any value other than 0
Serial.println("LED on");
digitalWrite(ledPin, HIGH); // will turn the LED on
} else { // a 0 value
Serial.println(F("LED off"));
digitalWrite(ledPin, LOW); // will turn the LED off
}
}
}
// when the central disconnects, print it out:
Serial.print(F("Disconnected from central: "));
Serial.println(central.address());
}
}
void updateBatteryLevel()
{
/* Read the current voltage level on the A0 analog input pin.
This is used here to simulate the charge level of a battery.
*/
int battery = analogRead(A0);
int batteryLevel = map(battery, 0, 1023, 0, 100);
if (batteryLevel != oldBatteryLevel) { // if the battery level has changed
// Serial.print("Battery Level % is now: "); // print it
Serial.println(batteryLevel);
batteryLevelChar.writeValue(batteryLevel); // and update the battery level characteristic
oldBatteryLevel = batteryLevel; // save the level for next comparison
}
}
void outputScale(){
int t, i, n, T;
double val, sum, sumsq, mean;
float stddev;
n = 20;
t = millis();
i = sum = sumsq = 0;
while (i<n) {
val = ((scale.read() - scale.get_offset()) / scale.get_scale());
sum += val;
sumsq += val * val;
i++;
}
t = millis() - t;
mean = sum / n;
stddev = sqrt(sumsq / n - mean * mean);
// Serial.print("Mean, Std Dev of "); Serial.print(i); Serial.print(" readings:\t");
Serial.print(sum / n, 3); Serial.print("\n"); // Serial.print(stddev, 3);
// Note: 2 sigma is 95% confidence, 3 sigma is 99.7%
//Serial.print("\nTime taken:\t"); Serial.print(float(t)/1000, 3); Serial.println("Secs\n");
/*
scale.power_down(); // put the ADC in sleep mode
delay(5000);
scale.power_up();
*/
}
You are initialising as scale.begin(A1, A0) while trying to read from the same A0 pin.

Rotary encoder strange behaviour

I have problem with results (on serial monitor) of rotary encoder.
I am using Arduino UNO and RotaryEncoder library.
When I am running example code serial monitor show proper values when rotating with any speed.
I want to use encoder to change volume in Df-player.
Problem starts when I want to use this code together with more complicated one - Mp3 player.
It actually works only when I am rotating encoder very very slowly
#include <SPI.h>
#include <MFRC522.h>
#include <Arduino.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
#include <RotaryEncoder.h>
#define RST_PIN 9 // Configurable, see typical pin layout above
#define SS_PIN 10 // Configurable, see typical pin layout above
#define PIN_IN1 2
#define PIN_IN2 3
#define ROTARYSTEPS 1
#define ROTARYMIN 0
#define ROTARYMAX 30
const int playPauseButton = 4;
const int shuffleButton = 5;
boolean isPlaying = false;
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
SoftwareSerial mySoftwareSerial(5, 6); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);
// Setup a RotaryEncoder with 2 steps per latch for the 2 signal input pins:
RotaryEncoder encoder(PIN_IN1, PIN_IN2, RotaryEncoder::LatchMode::TWO03);
// Last known rotary position.
int lastPos = -1;
//*****************************************************************************************//
void setup() {
Serial.begin(9600); // Initialize serial communications with the PC, COMMENT OUT IF IT FAILS TO PLAY WHEN DISCONNECTED FROM PC
mySoftwareSerial.begin(9600);
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
while (! Serial);
encoder.setPosition(5 / ROTARYSTEPS); // start with the value of 5.
pinMode(playPauseButton, INPUT_PULLUP);
pinMode(shuffleButton, INPUT_PULLUP);
Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
if (!myDFPlayer.begin(mySoftwareSerial)) { //Use softwareSerial to communicate with mp3.
Serial.println(F("Unable to begin:"));
Serial.println(F("1.Please recheck the connection!"));
Serial.println(F("2.Please insert the SD card!"));
}
Serial.println(F("DFPlayer Mini online. Place card on reader to play a spesific song"));
//myDFPlayer.volume(15); //Set volume value. From 0 to 30
//volumeLevel = map(analogRead(volumePot), 0, 1023, 0, 30); //scale the pot value and volume level
myDFPlayer.volume(5);
//prevVolume = volumeLevel;
//----Set different EQ----
myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
// myDFPlayer.EQ(DFPLAYER_EQ_POP);
// myDFPlayer.EQ(DFPLAYER_EQ_ROCK);
// myDFPlayer.EQ(DFPLAYER_EQ_JAZZ);
// myDFPlayer.EQ(DFPLAYER_EQ_CLASSIC);
// myDFPlayer.EQ(DFPLAYER_EQ_BASS);
}
//*****************************************************************************************//
void loop() {
encoder.tick();
// get the current physical position and calc the logical position
int newPos = encoder.getPosition() * ROTARYSTEPS;
if (newPos < ROTARYMIN) {
encoder.setPosition(ROTARYMIN / ROTARYSTEPS);
newPos = ROTARYMIN;
} else if (newPos > ROTARYMAX) {
encoder.setPosition(ROTARYMAX / ROTARYSTEPS);
newPos = ROTARYMAX;
} // if
if (lastPos != newPos) {
Serial.println(newPos);
myDFPlayer.volume(newPos);
lastPos = newPos;
} // if
// Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
MFRC522::MIFARE_Key key;
for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;
//some variables we need
byte block;
byte len;
MFRC522::StatusCode status;
if (digitalRead(playPauseButton) == LOW) {
if (isPlaying) {
myDFPlayer.pause();
isPlaying = false;
Serial.println("Paused..");
}
else {
isPlaying = true;
myDFPlayer.start();
Serial.println("Playing..");
}
delay(500);
}
if (digitalRead(shuffleButton) == LOW) {
myDFPlayer.randomAll();
Serial.println("Shuffle Play");
isPlaying = true;
delay(1000);
}
//-------------------------------------------
// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
if ( mfrc522.PICC_IsNewCardPresent()) {
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}
Serial.println(F("**Card Detected:**"));
//-------------------------------------------
mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid)); //dump some details about the card
//mfrc522.PICC_DumpToSerial(&(mfrc522.uid)); //uncomment this to see all blocks in hex
//-------------------------------------------
Serial.print(F("Number: "));
//---------------------------------------- GET NUMBER AND PLAY THE SONG
byte buffer2[18];
block = 1;
len = 18;
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 1, &key, &(mfrc522.uid)); //line 834
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Authentication failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
status = mfrc522.MIFARE_Read(block, buffer2, &len);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Reading failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
//PRINT NUMBER
String number = "";
for (uint8_t i = 0; i < 16; i++)
{
number += (char)buffer2[i];
}
number.trim();
Serial.print(number);
//PLAY SONG
myDFPlayer.play(number.toInt());
isPlaying = true;
//----------------------------------------
Serial.println(F("\n**End Reading**\n"));
delay(1000); //change value if you want to read cards faster
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
}
}
Any ideas what is wrong?
You have a delay(1000) in your main loop, and since your RotaryEncoder object seems to need a tick() function, i am assuming that it is not interrupt driven. This means that it will check only once per second if it has moved to the next step.
If a rotary encoder is stepped twice, and the middle step is missed by the MCU, the latter has no way of knowing which way round the encoder has turned.
So in this case you can only turn it one step per second.
What you need is, either:
a free running main loop, which goes round at least 100 times per second. (less nice)
a rotary encoder driver that is interrupt driven. (very nice)
I don't know if such a library exists, because i tend not to use arduino libs, but it is a very good exercise to write your own using GPIO interrupts.

Why receiving shifted and duplicated data in SPI communication between Raspberry Pi (master) and Nucleo l432kc boards (slaves)

​I've asked the same question on the ST Q&A forum and on the Raspberry Pi forum, but I didn't receive any answer. I hope that here there is someone that can help me.
I want to make communicate two Nucleo l432kc (slaves) with a Raspberry Pi (master) through the SPI protocol. On the Raspberry I'm using the Spidev API, while on the Nucleo I'm using the HAL SPI interface with DMA.
The only configuration that permits a stable transmission is the SPI_MODE_2 of Spidev that corresponds to the SPI_POLARITY_HIGH and SPI_PHASE_2EDGE configuration of the HAL.
With the above configuration I have two problems:
The messages sent by the master to the slaves arrive always correctly, but all the messages sent by the slaves to the master always arrive shifted by 1 bit on the right (e.g. if I send two bytes 0b00000011 0b00000001 I receive 0b00000001 0b10000000). It seems that the sampling of the MISO signal is delayed but I can't figure out why.
I receive the data on both the slaves regardless if the chip select is set or not. In the response of the slaves I have no collisions so I think that only the MISO bus is effectively set in high impedance mode in the slave when the NSS is high.
To test purpose I've tried to use the SPISlave class of the mbed framework,
this class cannot use the DMA so I can't use it in the real program. Using it I solve the first problem but the second persists.
Another thing that could be useful is that with the SPISlave class I can use all the 4 mode of the SPI protocol, of course the slaves and the master must use the same mode but is not import which one.
As I said before with the HAL interface I can use only the SPI_MODE_2.
This is the configuration code that runs on both the slaves:
// SPI
__HAL_RCC_SPI1_CLK_ENABLE();
/* SPI1 parameter configuration*/
hspi.Instance = SPI1;
hspi.Init.Mode = SPI_MODE_SLAVE;
hspi.Init.Direction = SPI_DIRECTION_2LINES; // full duplex mode
hspi.Init.DataSize = SPI_DATASIZE_8BIT; // dimension of 1 byte
hspi.Init.CLKPolarity = SPI_POLARITY_HIGH; // start and idle clk value
hspi.Init.CLKPhase = SPI_PHASE_2EDGE; // edge of sampling of data both on miso and mosi
hspi.Init.FirstBit = SPI_FIRSTBIT_MSB; // bit order
hspi.Init.TIMode = SPI_TIMODE_DISABLE; // disabling the TI mode
hspi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; // disable crc calc
hspi.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; // disable NSS puls value
if (HAL_SPI_Init(&hspi) != HAL_OK)
return false;
/* SPI1 interrupt Init */
HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
// GPIO
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA1 ------> SPI1_SCK
PA11 ------> SPI1_MISO
PA12 ------> SPI1_MOSI
PB0 ------> SPI1_NSS
*/
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
// DMA
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* SPI1 DMA Init */
/* SPI1_RX Init */
hdma_spi_rx.Instance = DMA1_Channel2;
hdma_spi_rx.Init.Request = DMA_REQUEST_1;
hdma_spi_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi_rx.Init.Mode = DMA_NORMAL;
hdma_spi_rx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_spi_rx) != HAL_OK) return false;
__HAL_LINKDMA(&hspi,hdmarx,hdma_spi_rx);
/* DMA interrupt init */
/* DMA1_Channel2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
/* SPI1 DMA Init */
/* SPI1_TX Init */
hdma_spi_tx.Instance = DMA1_Channel3;
hdma_spi_tx.Init.Request = DMA_REQUEST_1;
hdma_spi_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi_tx.Init.Mode = DMA_NORMAL;
hdma_spi_tx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_spi_tx) != HAL_OK) return false;
__HAL_LINKDMA(&hspi,hdmatx,hdma_spi_tx);
/* DMA interrupt init */
/* DMA1_Channel3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
And this is the code that runs on the master:
unsigned int bitsPerByte = 8u;
unsigned int delay = 0u;
unsigned int speed = 100; // hz
unsigned int cs_change = 0u; // false in C
// initialization
fd = ::open("/dev/spidev0.0", O_RDWR);
auto mode = SPI_MODE_2; // clock polarity low, clock phase second edge
if (fd == -1)
throw std::runtime_error("Can't open the spi device");
if (::ioctl(fd, SPI_IOC_WR_MODE, &mode) == -1)
throw std::runtime_error("Can't set the spi mode");
/*
* bits per word
*/
auto bits = bitsPerByte;
auto ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
throw std::runtime_error("can't set bits per word");
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
throw std::runtime_error("can't get bits per word");
/*
* max speed hz
*/
auto maxSpeed = speed;
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &maxSpeed);
if (ret == -1)
throw std::runtime_error("can't set max speed hz");
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &maxSpeed);
if (ret == -1)
throw std::runtime_error("can't get max speed hz");
// code used for sending messages
void transfer(uint8_t *tx, uint8_t *rx, size_t size) {
struct spi_ioc_transfer tr = {
(unsigned long)tx, // .tx_buf
(unsigned long)rx, // .rx_buf
size, // .len
speed, // .speed_hz
delay, // .delay_usecs
bitsPerByte, // .bits_per_word
cs_change, // .cs_change
0, // .tx_nbits
0, // .rx_nbits
0, // .pad
};
if (::ioctl(fd, SPI_IOC_MESSAGE(1), &tr) == -1)
throw std::runtime_error("Can't send data throught the spi");
}
In the main functions of the slaves the only thing that I actually do is to send back the exact packet that I receive.
EDIT
On the forum of the Raspberry someone told me to use piscope to see the digital value that is send on the pins. I've done it and I've seen that the CE0 and CE1 pin are always low. I can't understand why I do not have collisions on the MISO.
EDIT 2
I've solved the second problem (the duplicated data) it was an error on the master configuration, I was using cs_change = 1 but it must be equal to 0.
With piscope I've figured out that the slaves are sending the data correctly, it's the master that does not read them well.