Segmentation fault when changing value of attribute - c++11

I'm working in a C++11 class that will fetch via I2C the value of a temperature sensor in a Raspberry Pi. It will be polling the value until it's stopped. It does the polling in a separate thread, so that it does not stop the application flow. The problem is that in the line 64 of this file: https://github.com/OpenStratos/server/blob/feature/temperature/temperature/Temperature.cpp#L64
void Temperature::read_temperature()
{
while (this->reading)
{
#ifndef OS_TESTING
int value = wiringPiI2CRead(this->filehandle);
#else
int value = 16000;
#endif
float voltage = value * 5 / 32768; // 2^15
float temp = r_to_c(TEMP_R * (TEMP_VIN / voltage - 1));
this->temperature = temp; // Gives segmentation fault
this_thread::sleep_for(chrono::milliseconds(50));
}
}
it gives a segmentation fault. The curius thing is that it does not always happen. After compiling, running the binary many times about the 75% of the time will crash.
This is the file that invoques the code:https://github.com/OpenStratos/server/blob/feature/temperature/testing/temperature_test.cpp
Temperature temp(20);
temp.start_reading();
AssertThat(temp.is_reading(), Equals(true));
// this_thread::sleep_for(chrono::milliseconds(100)); if uncommented less segmentation faults
temp.stop_reading();
AssertThat(temp.is_reading(), Equals(false));
What could be happening? How can it be fixed?

You need to wait for Temperature::read_temperature() to quit, so you need:
bool reading;
volatile bool stopped; // volatile required to make the compiler re-read
// the value everytime we expect it to.
//
bool is_stopped(){ return stopped; }
and
void Temperature::start_reading()
{
if (!reading)
{
stopped = false;
reading = true;
// etc
and
void Temperature::read_temperature()
{
while (this->reading)
{
// etc
}
stopped=true;
}
and
temp.stop_reading();
while(!temp.is_stopped();
AssertThat(temp.is_reading(), Equals(false));

Related

FASTLED.show() stops working when working in core 1 FREERTOS (after deleting the task running a pattern and creating a new one)

I have a couple of pattern functions and one task (Task1) which runs on core 1. I receive data (pattern no.) from BLE in core 0. Depending on the data, I create the task above with the task function as the chosen pattern.
Problem comes when I want to switch patterns. What I do is delete the already running task handle (Task1) and recreate the same Task1 handle with the new pattern function. Sometimes the switch between patterns is flawless. But most times, the switch happens but the leds don't get updated. In the background I can see the new task has been created and the pattern looping as expected but the leds just don't get updated. They are stuck on the colors from the previous deleted task.
The switch of patterns:
`
TaskHandle_t Task1;
// if a new pattern no. has been read
if (command.startsWith("p"))
{
if (Task1 != NULL)
{
vTaskDelete(Task1);
}
xTaskCreatePinnedToCore(
switchPattern(command.substring(1).toInt()), /* Returns a task function. */
"Task1", /* name of task. */
20000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task1, /* Task handle to keep track of created task */
1); /* pin task to core 1 */
mode = 1; // switch to patterns mode
preferences.putInt("mode", mode);
}
**Example pattern function:**
void BPM(void *)
{
while (1)
{
// colored stripes pulsing at a defined Beats-Per-Minute (BPM)
uint8_t BeatsPerMinute = 62;
CRGBPalette16 palette = PartyColors_p;
uint8_t beat = beatsin8(BeatsPerMinute, 64, 255);
for (int i = 0; i < NUM_LEDS; i++)
{ // 9948
led[i] = ColorFromPalette(palette, (i * 2), beat + (i * 10));
}
FastLED.show();
}
}
`
If you know the fault or know a better way to do this, throw it at me.
Any help is appreciated!
I really can't find similar questions online so I haven't tried much.
I have tried not deleting the task at all, but that just adds more tasks to the core 1 hence showing multiple patterns at once, though FASTLED continues working normally. But this is not the expected result of course.
I expect the changing of patterns to be smooth. Maybe I'm missing something.
Creating a new task for a simple control flow branch is a nuclear overkill :) I suspect you don't need to create any threads whatsoever, as FastLED doesn't seem to require it in any way (didn't look too deep).
Assuming you have a LED blinking task, just signal to it which option you want. It can be done quite simply.
typedef enum {
LED_PATTERN_BPM,
LED_PATTERN_Y,
LED_PATTERN_Z
} led_pattern_t;
// "volatile" keyword required for any variable accessed in different threads
volatile led_pattern_t _led_pattern = LED_PATTERN_BPM;
// Single iteration of a flash pattern, no while(1) loop
void flash_pattern_BPM()
{
// colored stripes pulsing at a defined Beats-Per-Minute (BPM)
uint8_t BeatsPerMinute = 62;
CRGBPalette16 palette = PartyColors_p;
uint8_t beat = beatsin8(BeatsPerMinute, 64, 255);
for (int i = 0; i < NUM_LEDS; i++)
{ // 9948
led[i] = ColorFromPalette(palette, (i * 2), beat + (i * 10));
}
FastLED.show();
}
void flash_pattern_Z_interruptible() {
while (_led_pattern == LED_PATTERN_Z) {
// Fill the pattern, show it
}
}
// Task code for flashing the LEDs
void led_task(void* param) {
while (true) {
switch(_led_pattern) {
case LED_PATTERN_BPM:
flash_pattern_BPM();
break;
case LED_PATTERN_Y:
// Flash pattern Y
break;
case LED_PATTERN_Z:
flash_pattern_Z_interruptible();
break;
}
}
}
xTaskCreatePinnedToCore(led_task, "LED task", 20000, NULL, 1, &Task1, 1);
...
// Somewhere in your code where a new pattern is required
_led_pattern = LED_PATTERN_Z;

TIM2 module not ticking at 1us in STM8S103F3 controller

I created a program on STM8S103F3 to generate a delay in rage of micro seconds using TIM2 module, but the timer is not ticking as expected and when I tried to call 5 sec delay using it, it is giving around 3 sec delay. I'm using 16MHz HSI oscillator and timer pre-scalar is set to 16. please see my code below. Please help me to figure out what is wrong with my code.
void clock_setup(void)
{
CLK_DeInit();
CLK_HSECmd(DISABLE);
CLK_LSICmd(DISABLE);
CLK_HSICmd(ENABLE);
while(CLK_GetFlagStatus(CLK_FLAG_HSIRDY) == FALSE);
CLK_ClockSwitchCmd(ENABLE);
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);
CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSI,
DISABLE, CLK_CURRENTCLOCKSTATE_ENABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_SPI, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_ADC, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_AWU, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART1, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER1, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER2, DISABLE);
}
void delay_us(uint16_t us)
{
volatile uint16_t temp;
TIM2_DeInit();
TIM2_TimeBaseInit(TIM2_PRESCALER_16, 2000); //Prescalar value 8,Timer clock 2MHz
TIM2_Cmd(ENABLE);
do{
temp = TIM2_GetCounter();
}while(temp < us);
TIM2_ClearFlag(TIM2_FLAG_UPDATE);
TIM2_Cmd(DISABLE);
}
void delay_ms(uint16_t ms)
{
while(ms--)
{
//delay_us(1000);
delay_us(1000);
}
}
It is better to use a 10us time base to round the delays. Well in order to achive a 10us timebase, if you use 16MHz master clock and you prescale TIM2 by 16, then you get a 1 us increment time, right? But we want TIM2 to overflow to generate an event named 16us event. Since we know that the timer will increment every 1us, if we use a reload value 65536 - 10 = 65526, this will give us a 10us overflow hence, 10us time base. If we are ok until here in delay code we'll just check the TIM2 update flag to know whther it has overflowed or not. See the example code snippet below.
// Set up it once since our time base is a fixed 10us
void setupTIM2(){
TIM2_DeInit();
TIM2_TimeBaseInit(TIM2_PRESCALER_16, 65526); //Prescalar value 16,Timer clock 1MHz
}
void delay_us(uint16_t us)
{
volatile uint16_t temp;
TIM2_Cmd(ENABLE);
const uint16_t count = us / 10; //Get the required counts for 10us time base
// Loop until the temp reaches the required count value
do{
while(TIM2_GetFlagStatus(TIM2_FLAG_UPDATE) == RESET); //Wait for the TIM2 to overflow
TIM2_ClearFlag(TIM2_FLAG_UPDATE); // Clear the overflow flag
temp++;
} while(temp < count);
TIM2_Cmd(DISABLE);
}
void delay_ms(uint16_t ms)
{
while(ms--)
{
//delay_us(1000);
delay_us(1000);
}
}
void main(void){
...
setupTIM2();
...
delay_ms(5000);
}

Raspberry Pi Ultimate GPS Hat - UART buffer is completely filled with 0 values

In the meanwhile, I bought two Raspberry Pi Ultimate GPS Hat. I thought the first GPS Hat might be broken, but both of them shows the same behaviour - the buffer received from the UART, is completely filled with 0 values (512 bytes)!
See processBuffer(byte[] buffer, int count) Method in the NmeaGpsModule class.
private void processBuffer(byte[] buffer, int count) {
for (int i = 0; i < count; i++) {
if (mParser.getFrameStart() == buffer[i]) {
handleFrameStart();
} else if (mParser.getFrameEnd() == buffer[i]) {
handleFrameEnd();
} else if (buffer[i] != 0){
//Insert all other characters except '0's into the buffer
mMessageBuffer.put(buffer[i]);
}
}
}
I use the GPS example with the following settings:
public static final int UART_BAUD = 9600;
public static final float ACCURACY = 2.5f; // From GPS datasheet
Any ideas? Whats wrong?
Try to follow this post: UART peripherals on Android Things for Raspberry Pi 3
The console is flooding the serial with junk. Need to disable the output to clean that up.

Writing SSPBUF from variable in I2C slave protocol in PIC18

I am writing an I2C slave routine for PIC18F25K80 and I am stuck on a weird problem.
This is my routine:
void interrupt interruption_handler() {
PIE1bits.SSPIE = 0; // Disable Master Synchronous Serial Port Interrupt
if (PIR1bits.SSPIF != 1) {
//This is not I2C interruption;
PIE1bits.SSPIE = 1; // Enable Master Synchronous Serial Port Interrupt
return;
}
//Treat overflow
if ((SSPCON1bits.SSPOV) || (SSPCON1bits.WCOL)) {
dummy = SSPBUF; // Read the previous value to clear the buffer
SSPCON1bits.SSPOV = 0; // Clear the overflow flag
SSPCON1bits.WCOL = 0; // Clear the collision bit
SSPCON1bits.CKP = 1;
board_state = BOARD_STATE_ERROR;
} else {
if (!SSPSTATbits.D_NOT_A) {
//Slave address
debug(0, ON);
//Read address
address = SSPBUF; //Clear BF
while(BF); //Wait until completion
if (SSPSTATbits.R_NOT_W) {
SSPCON1bits.WCOL = 0;
unsigned char a = 0x01;
SSPBUF = a;//0x01 works //Deliver first byte
asm("nop");
}
} else {
if (SSPSTATbits.BF) {
dummy = SSPBUF; // Clear BF (just in case)
while(BF);
}
if (SSPSTATbits.R_NOT_W) {
//Multi-byte read
debug(1, ON);
SSPCON1bits.WCOL = 0;
SSPBUF = 0x02; //Deliver second byte
asm("nop");
} else {
//WRITE
debug(2, ON);
}
}
transmitted = TRUE;
SSPCON1bits.CKP = 1;
PIR1bits.SSPIF = 0;
PIE1bits.SSPIE = 1; // Enable Master Synchronous Serial Port Interrupt
}
}
It works like a charm if I set constant values on SSPBUF. For example, if you do:
SSPBUF = 0x01;
(...)
SSPBUF = 0x02;
I get the two bytes on the master. I can even see the wave forms of the bytes being transmitted on the oscilloscope. Quite fun!
But when I try to set SSPBUF using a variable like:
unsigned char a = 0x01;
SSPBUF = a;
I get zero on the master.
It is driving me crazy.
Some hypothesis I've discarded:
Watchdog timer is messing up interrupting in the middle of the protocol: It is not. It is disabled and the problem happens in both SSPBUF assignments
I need to wait until BF goes low to continue: I don't. AFAIK, you setup the SSPBUF, clear SSPIF, set CKP and return from interruption to take care of life in 4Mhz while the hardware send data in few Khz. It will interrupt you again when it finishes.
It makes no sense to me. How good it is if you cannot define an arbitrary value using a variable?
Please gurus out there, enlighten this poor programmer.
Thanks in advance.
It has something to do with how the compiler generates the code and some undocumented/unknown PIC restriction around SSPBUF (it is an special register anyway).
I found out that it works when the compiler uses movwf and does not work when the compiler uses movff.
I moved the question to another forum because I realized the audience there is more adequate.
You will find more details here:
https://electronics.stackexchange.com/questions/251763/writing-sspbuf-from-variable-in-i2c-slave-protocol-in-pic18/251771#251771
Try move declaration : "unsigned char a = 0x01;"
to the beginning of the function or try define it as volatile global variable.
take into accunte that SSPBUF is both read and write buffer.check if there are conditions that may cause I2C module to reset this buffer.

Arduino/MPU6050/AdafruitMotorShieldV2: script hangs/freezes when turn on motors

I'm a newby to robotics and electronics in general, so please don't assume I tried anything you might think is obvious.
I'm trying to create a cart which will basically run around by itself (simple AI routines to avoid obstacles, go from pt. A to pt. B around corners, follow lines, etc.). I'm putting together an Adafruit Arduino Uno R3 with the Adafruit Motor Shield v2 and an MPU-6050. I'm using the "breadboard" on the Motor Shield for the circuitry, soldering everything there.
I can get all the pieces working independently with their own scripts: the Motor Shield drives the 4 motors as expected using the Adafruit library; I'm using the "JRowberg" library for the MPU-6050, and started with the example MPU6050_DMP6.ino, which works fine as long as the cart motors are turned off. My only changes in the example script below are motor startup and some simple motor commands.
As long as I leave the switch which powers the motors off, everything seems fine: it outputs to the Serial window continuously with Euler data which, I assume, is correct. However, a few seconds after I turn on the power to the motors (and the wheels start turning), it just hangs/freezes: the output to the Serial window stops (sometimes in mid-line), and the wheels keep turning at the speed of their last change. Sometimes I see "FIFO overflow" errors, but not always. Sometimes I see "nan" for some of the floating point values before it hangs, but not always.
Some things I've tried, all of which changed noting:
* I've swapped out the MPU-6050 board for another from the same manufacturer.
* I've tried moving the MPU-6050 away from the motors using a ribbon cable.
* I've changed the I2C clock using JRowber's advice (a change in a .h file and changing the value of the TWBR variable), but I don't think I've tried all possible values.
* I've changed the speed of the MotorShield in the AFMS.begin() command, although, again, there are probably other values I haven't tried, and I'm not sure how in-sync this and the TWBR value need to be.
And some other things, all to no avail.
Below is an example script which fails for me:
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
#include "Adafruit_MotorShield.h"
#include "utility/Adafruit_PWMServoDriver.h"
#define DEBUG 1
MPU6050 mpu;
#define OUTPUT_READABLE_EULER
#define LED_PIN 13
bool blinkState = false;
bool dmpReady = false; // set true if DMP init was successful
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
Quaternion q; // [w, x, y, z] quaternion container
VectorInt16 aa; // [x, y, z] accel sensor measurements
VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements
VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements
VectorFloat gravity; // [x, y, z] gravity vector
float euler[3]; // [psi, theta, phi] Euler angle container
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
#define NUM_MOTORS 4
#define MOTOR_FL 0
#define MOTOR_FR 1
#define MOTOR_RR 2
#define MOTOR_RL 3
Adafruit_DCMotor *myMotors[NUM_MOTORS] = {
AFMS.getMotor(1),
AFMS.getMotor(2),
AFMS.getMotor(3),
AFMS.getMotor(4),
};
#define CHANGE_SPEED_TIME 500
long changeSpeedMillis = 0;
int curSpeed = 30;
volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
mpuInterrupt = true;
}
void setup() {
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
Serial.begin(115200);
while (!Serial); // wait for Leonardo enumeration, others continue immediately
// start the motor shield.
AFMS.begin(); // create with the default frequency 1.6KHz
// AFMS.begin(4000); // OR with a different frequency, say 4KHz
// kill all the motors.
myMotors[MOTOR_FL]->run(BRAKE);
myMotors[MOTOR_FL]->setSpeed(0);
myMotors[MOTOR_FR]->run(BRAKE);
myMotors[MOTOR_FR]->setSpeed(0);
myMotors[MOTOR_RR]->run(BRAKE);
myMotors[MOTOR_RR]->setSpeed(0);
myMotors[MOTOR_RL]->run(BRAKE);
myMotors[MOTOR_RL]->setSpeed(0);
Serial.println("Motor Shield ready!");
Serial.println(F("Initializing I2C devices..."));
mpu.initialize();
// verify connection
Serial.println(F("Testing device connections..."));
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
// wait for ready
Serial.println(F("\nSend any character to begin DMP programming and demo: "));
while (Serial.available() && Serial.read()); // empty buffer
while (!Serial.available()); // wait for data
while (Serial.available() && Serial.read()); // empty buffer again
// load and configure the DMP
Serial.println(F("Initializing DMP..."));
devStatus = mpu.dmpInitialize();
// supply your own gyro offsets here, scaled for min sensitivity
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
// make sure it worked (returns 0 if so)
if (devStatus == 0) {
// turn on the DMP, now that it's ready
Serial.println(F("Enabling DMP..."));
mpu.setDMPEnabled(true);
// enable Arduino interrupt detection
Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
// set our DMP Ready flag so the main loop() function knows it's okay to use it
Serial.println(F("DMP ready! Waiting for first interrupt..."));
dmpReady = true;
// get expected DMP packet size for later comparison
packetSize = mpu.dmpGetFIFOPacketSize();
} else {
// ERROR!
// 1 = initial memory load failed
// 2 = DMP configuration updates failed
// (if it's going to break, usually the code will be 1)
Serial.print(F("DMP Initialization failed (code "));
Serial.print(devStatus);
Serial.println(F(")"));
}
// configure LED for output
pinMode(LED_PIN, OUTPUT);
}
void loop() {
// if programming failed, don't try to do anything
if (!dmpReady) return;
// wait for MPU interrupt or extra packet(s) available
while (!mpuInterrupt && fifoCount < packetSize) {
// as per Vulpo's post.
delay(10);
if (millis() > changeSpeedMillis) {
curSpeed += 20;
if (curSpeed > 256) {
curSpeed = 30;
}
Serial.print("changing speed to: ");
Serial.println(curSpeed);
myMotors[MOTOR_FL]->run(FORWARD);
myMotors[MOTOR_FL]->setSpeed(curSpeed);
myMotors[MOTOR_FR]->run(FORWARD);
myMotors[MOTOR_FR]->setSpeed(curSpeed);
myMotors[MOTOR_RR]->run(FORWARD);
myMotors[MOTOR_RR]->setSpeed(curSpeed);
myMotors[MOTOR_RL]->run(FORWARD);
myMotors[MOTOR_RL]->setSpeed(curSpeed);
changeSpeedMillis = millis() + CHANGE_SPEED_TIME;
}
}
// reset interrupt flag and get INT_STATUS byte
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
// get current FIFO count
fifoCount = mpu.getFIFOCount();
// check for overflow (this should never happen unless our code is too inefficient)
if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
// reset so we can continue cleanly
mpu.resetFIFO();
Serial.println(F("FIFO overflow!"));
// otherwise, check for DMP data ready interrupt (this should happen frequently)
} else if (mpuIntStatus & 0x02) {
// wait for correct available data length, should be a VERY short wait
while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
// read a packet from FIFO
mpu.getFIFOBytes(fifoBuffer, packetSize);
// track FIFO count here in case there is > 1 packet available
// (this lets us immediately read more without waiting for an interrupt)
fifoCount -= packetSize;
#ifdef OUTPUT_READABLE_EULER
// display Euler angles in degrees
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetEuler(euler, &q);
Serial.print("euler\t");
Serial.print(euler[0] * 180/M_PI);
Serial.print("\t");
Serial.print(euler[1] * 180/M_PI);
Serial.print("\t");
Serial.println(euler[2] * 180/M_PI);
#endif
// blink LED to indicate activity
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
}
}
Have you considered that your troubles are caused by interference from the currents flowing into your motors?
If your motors are DC brush, then more interference may be radiated from the brushes back into your various wires.
As a first step, perhaps let only one motor work and see if hangups diminish in frequency (although, to be sure, you need a 'scope onto a few wires carrying logic signals.

Resources