bababwll
Posts: 4
Joined: Wed Nov 27, 2019 2:29 am

raspberry pi3 HX711 using loadcell Segmentation fault

Sun Dec 01, 2019 7:58 am


https://github.com/compugician/music-bottles-4


I changed the code to measure the load cell weight by referring to the URL address above, but when I run it, I get a segmentation fault. Can I ask for a solution?

Header File

Code: Select all

#include <stdio.h>
#include "gb_common.h"
#include <sched.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

//Scale (HX711) connections
//#define CLOCK_PIN	24
//#define CLOCK_PIN	26

//#define CLOCK_PIN	13
#define CLOCK_PIN	9

//#define DATA_PIN	23
//#define DATA_PIN	18
//#define DATA_PIN	15
//#define DATA_PIN	14

//#define DATA_PIN	19
#define DATA_PIN	11

//GPIO parameters
#define SCK_ON  (GPIO_SET0 = (1 << CLOCK_PIN))
#define SCK_OFF (GPIO_CLR0 = (1 << CLOCK_PIN))
#define DT_R    (GPIO_IN0  & (1 << DATA_PIN))

void setHighPri(void);

void begin();

void finish();

void reset_converter(void);

void set_gain(int r);

long read_average(int times);

float speedTest();

long getCleanSample(int numSamples, int spread);

unsigned long  read_value();

double get_value(int times);

float get_units(int times);

void set_scale(float scale);

void tare(int times);

void set_offset(long offset);


C code

Code: Select all

#include "hx711.h"

//#define N_SAMPLES	20
#define SPREAD		10
float SCALE = 1;
long OFFSET = 0;
/**

	HX711 interface for Raspberry Pi 3
	Based on code by gurov (https://github.com/ggurov/hx711) adapted to work on Pi3

*/



void setHighPri(void)
{
	struct sched_param sched;

	memset(&sched, 0, sizeof(sched));

	sched.sched_priority = 10;
	if (sched_setscheduler(0, SCHED_FIFO, &sched))
		printf("Warning: Unable to set high priority\n");
}


void setup_gpio()
{
	INP_GPIO(DATA_PIN);
	INP_GPIO(CLOCK_PIN);  OUT_GPIO(CLOCK_PIN);
	SCK_OFF;
}

void unpull_pins()
{
	GPIO_PULL = 0;
	//   short_wait();
	GPIO_PULLCLK0 = 1 << DATA_PIN;
	//   short_wait();
	GPIO_PULL = 0;
	GPIO_PULLCLK0 = 0;
} // unpull_pins

//hack for testing what works on the faster Pi3, see below - should probably be replaced with proper usleep
void delay(int i) {
	static clock_t timer;
	timer = clock();
	while (clock() - timer < i);
}


/**
 getCleanSample(int numSamples, int spread)

 get a clean sample, by sampling numSamples times, and averaging while filtering out any samples outside the specified filter spread

 will try a maximum of 10 times in a row to get a clean sample, fails with value of 0
*/
long getCleanSample(int numSamples, int spread) {

	int i, j = 0, k = 0;
	long tmp = 0;
	long tmp_avg = 0;
	long tmp_avg2;
	long offset = 0;
	float filter_low, filter_high;
	float spread_percent = spread / 100.0 / 2.0;
	int b;
	long samples[numSamples];


	while (j == 0 && k < 10) {
		k++;

		tmp_avg = 0;

		// get the dirty samples and average them
		for (i = 0; i < numSamples; i++) {
			samples[i] = read_value();
			tmp_avg += samples[i];
		}

		//calculate dirty average
		tmp_avg = tmp_avg / numSamples;

		tmp_avg2 = 0;

		j = 0;

		filter_low = (float)tmp_avg * (1.0 - spread_percent);
		filter_high = (float)tmp_avg * (1.0 + spread_percent);

		for (i = 0; i < numSamples; i++) {
			if ((samples[i] <= filter_high && samples[i] >= filter_low) ||
				(samples[i] >= filter_high && samples[i] <= filter_low)) {
				tmp_avg2 += samples[i];
				j++;
			}
		}

	}

	return tmp_avg2 / j;
}

/**
 speedTest runs 100 samples, and returns
*/
float speedTest() {
	int i;
	clock_t t1, t2;

	reset_converter();

	t1 = clock();
	for (i = 0; i < 100; i++) {
		read_value();
	}

	t2 = clock();

	float diff = ((float)(t2 - t1) / CLOCKS_PER_SEC) * 1000;
	float sps = 1000 / (diff / 100);

	//printf("%d samples took %f ms, %f sps\n",N_SAMPLES, diff, sps);

	return sps;
}


void finish() {
	unpull_pins();
	restore_io();
}


void reset_converter(void) {
	SCK_ON;
	//fseek(60);
	usleep(60);
	SCK_OFF;
	//fseek(60);
	usleep(60);
}

// r = 0 - Ch.A, Gain 128
// r = 1 - Ch.B, Gain 64
// r = 2 - Ch.A, Gain 32 <<<**** Different data sheets say different things about this configuration. Do not rely on this just working - test in your setup.
static int gain = 0; //default Ch.a, Gain 128
void set_gain(int r) {
	int i;
	gain = r;

	//wait for data ready
	while (DT_R);

	//pull out a reading and configure appropriately for next reading
	for (i = 0; i < 24 + r + 1; i++) {
		SCK_ON;
		SCK_OFF;
	}
}

void begin() {
	setHighPri();
	setup_gpio();
	reset_converter();
}



unsigned long read_value() {
	long count; //store the shifted-in data
	int i; 		//iterator

	count = 0;

	//can be replaced with a proper usleep
	const int DELAYLENGTH = 4;

	//white for Data Ready
	while (DT_R);

	delay(DELAYLENGTH);

	//read in the data
	for (i = 0; i < 24; i++) {
		SCK_ON;
		delay(DELAYLENGTH);
		if (DT_R > 0) { count++; }
		SCK_OFF;
		delay(DELAYLENGTH);
		count = count << 1;
	}

	//set gain for next reading
	for (i = 0; i < gain + 1; i++) {
		SCK_ON;
		delay(DELAYLENGTH);

		SCK_OFF;
		delay(DELAYLENGTH);
	}


	//TODO: check correctness for negative values!
	//  count = ~0x1800000 & count;
	//  count = ~0x800000 & count;
	if (count & 0x800000) {
		count |= (long)~0xffffff;
	}

	/*
	for (int i = 31; i >= 0; i--) {
		printf("%d ", ((count) & (1 << i)) != 0);
	}
	*/

	printf("n: %10ld     -  ", count);
	printf("\n");


	return count;
}

long read_average(int times) {
	int i, j;
	//long tmp=0;
	long tmp_avg = 0;
	long tmp_avg2;
	long offset = 0;
	float filter_low, filter_high;
	float spread_percent = SPREAD / 100.0 / 2.0;
	//int b;
	int nsamples = times;
	long samples[nsamples];


	j = 0;

	for (i = 0; i < nsamples; i++) {
		reset_converter();
		//read
		samples[i] = read_value();
		//read average
		tmp_avg += samples[i];
	}
	tmp_avg = tmp_avg / nsamples;


	tmp_avg2 = 0;
	j = 0;

	filter_low = (float)tmp_avg * (1.0 - spread_percent);
	filter_high = (float)tmp_avg * (1.0 + spread_percent);

	printf("%d %d\n", (int)filter_low, (int)filter_high);

	for (i = 0; i < nsamples; i++) {
		if ((samples[i] < filter_high && samples[i] > filter_low) ||
			(samples[i] > filter_high&& samples[i] < filter_low)) {
			tmp_avg2 += samples[i];
			j++;
		}
	}
	printf("J value: %d \n", j);

	if (j == 0) {
		printf("No data to consider\n");
		exit(255);

	}
	printf("%ld\n", (tmp_avg2 / j) - 0);

	return (tmp_avg2 / j) - 0;

}
double get_value(int times) {
	return (read_average(times) - 0);
}
float get_units(int times) {
	return (get_value(times) / SCALE);
}
void set_scale(float scale) {
	SCALE = scale;
}
void tare(int times) {
	double sum = read_average(times);
	set_offset(sum);
}
void set_offset(long offset) {
	OFFSET = offset;
}
void power_down() {
	SCK_OFF;
	SCK_ON;
}
void power_up() {
	SCK_OFF;
}

int main()
{

	//get loadcell data
	long result1;

	//itit
	begin();
	printf("init\n");


	result1 = read_average(10);
	printf("read_average_result1: ld \n", result1);

	//get_value(5);
	//result1 = get_value(5);
	//printf("get_value_result1: lf \n", result1);

	//get_units(5);
	//result1 = get_units(5);
	//printf("get_units: ld \n", result1);

	//set_scale(2280.f);

	//tare(10);

	//result1 = read_average(10);
	//printf("read_average_result1: ld \n", result1);

	//get_value(5);
	//result1 = get_value(5);
	//printf("get_value_result1: lf \n", result1);

	//get_units(5);
	//result1 = get_units(5);
	//printf("get_units: ld \n", result1);

	printf("Readings:");

	
	while (1) {
		result1= read_average(1);
		printf("1: %fg \n", result1);
		power_down();
		usleep(60);
		power_up();

	}

	//exit
	finish();

	return 0;
}


User avatar
joan
Posts: 14470
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: raspberry pi3 HX711 using loadcell Segmentation fault

Sun Dec 01, 2019 9:01 am

Unchange the code? Does it still give a segmentation fault.

bababwll
Posts: 4
Joined: Wed Nov 27, 2019 2:29 am

Re: raspberry pi3 HX711 using loadcell Segmentation fault

Sun Dec 01, 2019 3:38 pm

Yes, I try your code.

User avatar
DaveCooper
Posts: 19
Joined: Wed Jan 25, 2017 11:08 pm
Location: Norfolk, UK
Contact: Website

Re: raspberry pi3 HX711 using loadcell Segmentation fault

Mon Dec 02, 2019 3:14 pm

I've had a few segmentation faults over the years and I think I remember that they were caused by either trying to write to memory locations that didn't exist (eg running off the end of an EEPROM) or trying to write to memory locations which weren't accessible (eg files with wrong permissions). For sure the name isn't much of a clue! Dave

Heater
Posts: 13866
Joined: Tue Jul 17, 2012 3:02 pm

Re: raspberry pi3 HX711 using loadcell Segmentation fault

Mon Dec 02, 2019 10:48 pm

There are so many ways to make a memory access error in C/C++ that it amazing anything ever works.

If you get a segfault you are lucky. That is at least something on can get a handle on to debug.

What to do?

1) People frown upon it but debugging by printf is a tried an true method to find such bugs. Just put some printf's around the code and convince yourself those statements do actually get run. When you get to one that does not print you know where to look for the problem.

2) Enable the generation of core dumps and use the gdb debugger to show you were the problem is : https://developer.toradex.com/knowledge ... s-in-linux
Memory in C++ is a leaky abstraction .

User avatar
rpdom
Posts: 15572
Joined: Sun May 06, 2012 5:17 am
Location: Chelmsford, Essex, UK

Re: raspberry pi3 HX711 using loadcell Segmentation fault

Tue Dec 03, 2019 6:17 am

Heater wrote:
Mon Dec 02, 2019 10:48 pm
1) People frown upon it but debugging by printf is a tried an true method to find such bugs. Just put some printf's around the code and convince yourself those statements do actually get run. When you get to one that does not print you know where to look for the problem.
This is my usual method of debugging when developing software in almost any language. It works, most of the time.

Return to “C/C++”