Merge pull request #13 from alanbjohnston/ina-test

All C code I2C sensor reading
pull/24/head
alanbjohnston 7 years ago committed by GitHub
commit 48e9c51d3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -2,11 +2,13 @@ all: DEBUG_BEHAVIOR=
all: libax5043.a
all: radioafsk
all: radiocw
all: telem
debug: DEBUG_BEHAVIOR = -DDEBUG_LOGGING
debug: libax5043.a
debug: radioafsk
debug: radiocw
debug: telem
rebuild: clean
rebuild: all
@ -28,6 +30,7 @@ clean:
rm -f */*/*.o
rm -rf ax5043/doc/html
rm -rf ax5043/doc/latex
rm -f telem
docs:
mkdir -p ax5043/doc; cd ax5043; doxygen Doxyfile
@ -57,7 +60,7 @@ radiocw: cw/cw_main.o
radiocw: afsk/ax25.o
radiocw: afsk/ax5043.o
radiocw: afsk/send_afsk.o
gcc -std=gnu99 $(DEBUG_BEHAVIOR) -o radiocw -L./ afsk/ax25.o afsk/ax5043.o afsk/send_afsk.o cw/cw_main.o -lwiringPi -lax5043
gcc -std=gnu99 $(DEBUG_BEHAVIOR) -o radiocw -L./ afsk/ax25.o afsk/ax5043.o afsk/send_afsk.o cw/cw_main.o -lwiringPi -lax5043 -lcurl
radiopiglatin: libax5043.a
radiopiglatin: piglatin/piglatin_main.o
@ -69,29 +72,30 @@ testax5043tx: transmit/transmit_main.o
testax5043rx: libax5043.a
testax5043rx: receive/receive_main.o
gcc -std=gnu99 $(DEBUG_BEHAVIOR) -o testax5043rx -pedantic -Wall -Wextra -L./ receive/receive_main.o -lwiringPi -lax5043
gcc -std=gnu99 $(DEBUG_BEHAVIOR) -o testax5043rx -pedantic -Wall -Wextra -L./ receive/receive_main.o -lwiringPi -lax5043 -lcurl
testax5043init: libax5043.a
testax5043init: init/init_main.o
gcc -std=gnu99 $(DEBUG_BEHAVIOR) -o testax5043init -pedantic -Wall -Wextra -L./ init/init_main.o -lwiringPi -lax5043
gcc -std=gnu99 $(DEBUG_BEHAVIOR) -o testax5043init -pedantic -Wall -Wextra -L./ init/init_main.o -lwiringPi -lax5043 -lcurl
testax50432freq: libax5043.a
testax50432freq: transmit2freq/transmit2freq_main.o
gcc -std=gnu99 $(DEBUG_BEHAVIOR) -o testax50432freq -pedantic -Wall -Wextra -L./ transmit2freq/transmit2freq_main.o -lwiringPi -lax5043
gcc -std=gnu99 $(DEBUG_BEHAVIOR) -o testax50432freq -pedantic -Wall -Wextra -L./ transmit2freq/transmit2freq_main.o -lwiringPi -lax5043 -lcurl
testafsktx: libax5043.a
testafsktx: afsktx/ax25.o
testafsktx: afsktx/ax5043.o
testafsktx: afsktx/main.o
gcc -std=gnu99 $(DEBUG_BEHAVIOR) -o testafsktx -pedantic -Wall -Wextra -L./ afsktx/ax25.o afsktx/ax5043.o afsktx/main.o -lwiringPi -lax5043
gcc -std=gnu99 $(DEBUG_BEHAVIOR) -o testafsktx -pedantic -Wall -Wextra -L./ afsktx/ax25.o afsktx/ax5043.o afsktx/main.o -lwiringPi -lax5043 -lcurl
radioafsk: libax5043.a
radioafsk: afsk/ax25.o
radioafsk: afsk/ax5043.o
radioafsk: afsk/main.o
radioafsk: afsk/ina219.h
gcc -std=gnu99 $(DEBUG_BEHAVIOR) -o radioafsk -pedantic -Wall -Wextra -L./ afsk/ax25.o afsk/ax5043.o afsk/main.o -lwiringPi -lax5043
gcc $(DEBUG_BEHAVIOR) -o radioafsk -pedantic -Wall -Wextra -L./ afsk/ax25.o afsk/ax5043.o afsk/main.o -lwiringPi -lax5043 -lcurl
telem: afsk/telem.o
gcc $(DEBUG_BEHAVIOR) -o telem -pedantic -Wall -Wextra -L./ afsk/telem.o -lwiringPi
ax5043/generated/configcommon.o: ax5043/generated/configcommon.c
ax5043/generated/configcommon.o: ax5043/generated/configrx.h
@ -232,8 +236,13 @@ afsk/main.o: afsk/status.h
afsk/main.o: afsk/ax5043.h
afsk/main.o: afsk/ax25.h
afsk/main.o: ax5043/spi/ax5043spi.h
afsk/main.o: afsk/Adafruit_INA219.h
cd afsk; gcc -std=gnu99 $(DEBUG_BEHAVIOR) -I ../ax5043 -pedantic -Wconversion -Wall -Wextra -c main.c; cd ..
afsk/telem.o: afsk/telem.c
afsk/telem.o: afsk/Adafruit_INA219.h
cd afsk; gcc -std=gnu99 $(DEBUG_BEHAVIOR) -I ../ax5043 -pedantic -Wconversion -Wall -Wextra -c telem.c; cd ..
afsk/send_afsk.o: afsk/send_afsk.c
afsk/send_afsk.o: afsk/send_afsk.h
afsk/send_afsk.o: afsk/status.h

@ -18,8 +18,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <curl/curl.h>
#include "ax25.h"
#include <string.h>
#include <time.h>
#include <stdio.h>
#include "ax5043.h"
#include "status.h"
@ -88,6 +91,55 @@ int ax25_tx_frame(ax25_conf_t *hax25, ax5043_conf_t *hax,
memcpy(__tx_buffer, hax25->addr_field, hax25->addr_field_len);
memcpy(__tx_buffer + hax25->addr_field_len, payload, len);
#ifdef SATNOGS
printf("\n");
char post_data[1024];
char hex_data[512];
char hex_octet[4];
time_t t = time(NULL);
struct tm tm = *localtime(&t);
memset(post_data,0,strlen(post_data));
memset(hex_data,0,strlen(hex_data));
//printf("1:%s\n",post_data);
int jj;
for(jj = 0; jj < 118; jj++) {
sprintf(hex_octet, "%02x",__tx_buffer[jj]);
strcat(hex_data, hex_octet);
} // Note assumes EDT, change offset (+4) to UTC
sprintf(post_data,"noradID=99999&source=KU2Y&timestamp=%d-%d-%dT%d:%d:%d.500Z&frame=%s&locator=longLat&longitude=75.3492W&latitude=40.0376N&&azimuth=360&elevation=90.0", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, (tm.tm_hour + 4) % 24, tm.tm_min, tm.tm_sec, hex_data);
printf("curl post data: %s\n",post_data);
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(curl) {
//curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
curl_easy_setopt(curl, CURLOPT_URL, "https://db.satnogs.org/api/telemetry/");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data);
/* if we don't provide POSTFIELDSIZE, libcurl will strlen() by
itself */
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(post_data));
/* example.com is redirected, so we tell libcurl to follow redirection */
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "ERROR: AX25.C curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
#endif
return ax5043_tx_frame(hax, __tx_buffer, len + hax25->addr_field_len,
hax25->preamble_len, hax25->postable_len, 1000);

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
/*
* Transmits CubeSat Telemetry at 440MHz in AO-7 format
* Transmits CubeSat Telemetry at 434.9MHz in AO-7 format
*
* Copyright Alan B. Johnston
*
@ -17,9 +17,12 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* INA219 Raspberry Pi wiringPi code is based on Adafruit Arduino wire code
* from https://github.com/adafruit/Adafruit_INA219.
*/
#include <fcntl.h> //Needed for I2C port
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
@ -31,31 +34,23 @@
#include <wiringPiI2C.h>
#include <wiringPi.h>
#include <time.h>
#include "ina219.h"
#define CALLSIGN "" // Put your callsign here!
#define VBATT 15
#define ADC5 17
#define ADC6 18
#define ADC7 19
#define ADC8 20
#define TIME 8
#define UCTEMP 30
#define UPTIME_SEC 8
#include <math.h>
#include "../Adafruit_INA219/Adafruit_INA219.h" // From Adafruit INA219 library for Arduino
#define A 1
#define B 2
#define C 3
#define D 4
#define SENSOR_40 0
#define SENSOR_41 3
#define SENSOR_44 6
#define SENSOR_45 9
#define SENSOR_4A 12
#define VOLTAGE 0
#define CURRENT 1
#define POWER 2
#define VBATT 15
#define PLUS_X 0
#define PLUS_Y 1
#define PLUS_Z 2
#define BAT 3
#define MINUS_X 4
#define MINUS_Y 5
#define MINUS_Z 6
#define BUS 7
#define OFF -1
uint32_t tx_freq_hz = 434900000 + FREQUENCY_OFFSET;
uint32_t tx_channel = 0;
@ -64,42 +59,127 @@ ax5043_conf_t hax5043;
ax25_conf_t hax25;
static void init_rf();
int twosToInt(int val, int len);
int get_tlm(int tlm[][5]);
long int timestamp;
void config_x25();
void trans_x25();
//long int timestamp;
int tempSensor;
int upper_digit(int number);
int lower_digit(int number);
int charging = 0;
uint16_t config = (0x2000 | 0x1800 | 0x0180 | 0x0018 | 0x0007 );
struct SensorConfig {
int fd;
uint16_t config;
int calValue;
int powerMultiplier;
int currentDivider;
};
struct SensorData {
double current;
double voltage;
double power;
};
/**
* @brief Read the data from one of the i2c current sensors.
*
* Reads the current data from the requested i2c current sensor configuration and
* stores it into a SensorData struct. An invalid file descriptor (i.e. less than zero)
* results in a SensorData struct being returned that has both its #current and #power members
* set to NAN.
*
* @param sensor A structure containing sensor configuration including the file descriptor.
* @return struct SensorData A struct that contains the current, voltage, and power readings
* from the requested sensor.
*/
struct SensorData read_sensor_data(struct SensorConfig sensor) {
struct SensorData data = {
.current = NAN,
.voltage = NAN,
.power = NAN };
if (sensor.fd < 0) {
return data;
}
// doesn't read negative currents accurately, shows -0.1mA
wiringPiI2CWriteReg16(sensor.fd, INA219_REG_CALIBRATION, sensor.calValue);
wiringPiI2CWriteReg16(sensor.fd, INA219_REG_CONFIG, sensor.config);
wiringPiI2CWriteReg16(sensor.fd, INA219_REG_CALIBRATION, sensor.calValue);
int value = wiringPiI2CReadReg16(sensor.fd, INA219_REG_CURRENT);
data.current = (float) twosToInt(value, 16) / (float) sensor.currentDivider;
wiringPiI2CWrite(sensor.fd, INA219_REG_BUSVOLTAGE);
delay(1); // Max 12-bit conversion time is 586us per sample
value = (wiringPiI2CRead(sensor.fd) << 8 ) | wiringPiI2CRead (sensor.fd);
data.voltage = ((float)(value >> 3) * 4) / 1000;
// power has very low resolution, seems to step in 512mW values
data.power = (float) wiringPiI2CReadReg16(sensor.fd, INA219_REG_POWER) * (float) sensor.powerMultiplier;
return data;
}
/**
* @brief Configures an i2c current sensor.
*
* Calculates the configuration values of the i2c sensor so that
* current, voltage, and power can be read using read_sensor_data.
* Supports 16V 400mA and 16V 2.0A settings.
*
* @param sensor A file descriptor that can be used to read from the sensor.
* @param milliAmps The mA configuration, either 400mA or 2A are supported.
* @return struct SensorConfig A struct that contains the configuraton of the sensor.
*/
//struct SensorConfig config_sensor(int sensor, int milliAmps) {
struct SensorConfig config_sensor(char *bus, int address, int milliAmps) {
struct SensorConfig data;
if (access(bus, W_OK | R_OK) < 0) { // Test if I2C Bus is missing
printf("ERROR: %s bus not present \n", bus);
data.fd = OFF;
return (data);
}
data.fd = wiringPiI2CSetupInterface(bus, address);
data.config = INA219_CONFIG_BVOLTAGERANGE_32V |
INA219_CONFIG_GAIN_1_40MV |
INA219_CONFIG_BADCRES_12BIT |
INA219_CONFIG_SADCRES_12BIT_1S_532US |
INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS;
if (milliAmps == 400) { // INA219 16V 400mA configuration
data.calValue = 8192;
data.powerMultiplier = 1;
data.currentDivider = 20; // 40; in Adafruit config
}
else { // INA219 16V 2A configuration
data.calValue = 40960;
data.powerMultiplier = 2;
data.currentDivider = 10; // 20; in Adafruit config
}
#ifdef DEBUG_LOGGING
printf("Sensor %s %x configuration: %d %d %d %d %d\n", bus, address, data.fd,
data.config, data.calValue, data.currentDivider, data.powerMultiplier);
#endif
return data;
}
struct SensorConfig sensor[8]; // 7 current sensors in Solar Power PCB plus one in MoPower UPS V2
struct SensorData reading[8]; // 7 current sensors in Solar Power PCB plus one in MoPower UPS V2
struct SensorConfig tempSensor;
int x_fd; // I2C bus 0 address 0x40
int x_powerMultiplier;
int x_currentDivider;
int x_calValue;
int y_fd; // I2C bus 0 address 0x41
int z_fd; // I2C bos 0 address 0x44
char src_addr[5] = "";
char dest_addr[5] = "CQ";
int main(int argc, char *argv[]) {
if (argc > 1) {
strcpy(src_addr, argv[1]);
}
wiringPiSetup () ;
pinMode (0, OUTPUT) ;
int blink;
for (blink = 1; blink < 4 ;blink++)
{
digitalWrite (0, HIGH) ; delay (500) ;
digitalWrite (0, LOW) ; delay (500) ;
strcpy(src_addr, argv[1]);
}
digitalWrite (0, HIGH) ;
wiringPiSetup ();
pinMode (0, OUTPUT);
setSpiChannel(SPI_CHANNEL);
setSpiSpeed(SPI_SPEED);
@ -108,87 +188,25 @@ int main(int argc, char *argv[]) {
int tlm[7][5];
memset(tlm, 0, sizeof tlm);
timestamp = time(NULL);
int file_i2c = access("/dev/i2c-3", W_OK | R_OK);
//char *filenam1e = (char*)"/dev/i2c-3";
if (file_i2c < 0)
{
fprintf(stderr,"ERROR: /dev/ic2-3 bus not present\n");
tempSensor = -1;
} else
{
tempSensor = wiringPiI2CSetupInterface("/dev/i2c-3", 0x48);
}
#ifdef DEBUG_LOGGING
fprintf(stderr,"tempSensor: %d \n",tempSensor);
#endif
int arduinoI2C = access("/dev/i2c-0", W_OK | R_OK);
if (arduinoI2C < 0)
{
fprintf(stderr,"ERROR: /dev/i2c-0 bus not present\n");
} else {
arduinoI2C = wiringPiI2CSetupInterface("/dev/i2c-0", 0x4B);
#ifdef DEBUG_LOGGING
fprintf(stderr,"arduinoI2C: %d\n", arduinoI2C);
#endif
if (arduinoI2C > 0) {
if(wiringPiI2CReadReg16(arduinoI2C,0) < 0) {
arduinoI2C = -1; // Disable reading of Arduino payload information
fprintf(stderr,"Arduino payload not present\n");
}
} else {
fprintf(stderr,"Arduino payload not present\n");
}
}
// new INA219 current reading code
x_calValue = 8192;
x_powerMultiplier = 1;
x_currentDivider = 20;
config = INA219_CONFIG_BVOLTAGERANGE_16V |
INA219_CONFIG_GAIN_40MV |
INA219_CONFIG_BADCRES_12BIT |
INA219_CONFIG_SADCRES_12BIT_4S_2130US |
//INA219_CONFIG_SADCRES_12BIT_1S_532US |
INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS;
file_i2c = access("/dev/i2c-0", W_OK | R_OK);
if (file_i2c < 0)
{
fprintf(stderr,"ERROR: /dev/ic2-0 bus not present\n");
x_fd = -1; // Disable reading -X, -Y, and -Z telemetry
y_fd = -1;
z_fd = -1;
} else
{
x_fd = wiringPiI2CSetupInterface("/dev/i2c-0", 0x40);
y_fd = wiringPiI2CSetupInterface("/dev/i2c-0", 0x41);
z_fd = wiringPiI2CSetupInterface("/dev/i2c-0", 0x44);
#ifdef DEBUG_LOGGING
fprintf(stderr, "Opening of -X fd %d\n", x_fd);
fprintf(stderr, "Opening of -Y fd %d\n", y_fd);
fprintf(stderr, "Opening of -Z fd %d\n", z_fd);
#endif
}
tempSensor = config_sensor("/dev/i2c-3", 0x48, 0);
sensor[PLUS_X] = config_sensor("/dev/i2c-1", 0x40, 400);
sensor[PLUS_Y] = config_sensor("/dev/i2c-1", 0x41, 400);
sensor[PLUS_Z] = config_sensor("/dev/i2c-1", 0x44, 400);
sensor[BAT] = config_sensor("/dev/i2c-1", 0x45, 400);
sensor[BUS] = config_sensor("/dev/i2c-1", 0x4a, 2000);
sensor[MINUS_X] = config_sensor("/dev/i2c-0", 0x40, 400);
sensor[MINUS_Y] = config_sensor("/dev/i2c-0", 0x41, 400);
sensor[MINUS_Z] = config_sensor("/dev/i2c-0", 0x44, 400);
int ret;
uint8_t data[1024];
tx_freq_hz -= tx_channel * 50000 + 85000; // subtracting rx offset of 90kHz
tx_freq_hz -= tx_channel * 50000;
init_rf();
// ax25_init(&hax25, (uint8_t *) "CubeSatSim", '2', (uint8_t *) CALLSIGN, '2',
// ax25_init(&hax25, (uint8_t *) "CQ", '1', (uint8_t *) CALLSIGN, '1',
ax25_init(&hax25, (uint8_t *) dest_addr, '1', (uint8_t *) src_addr, '1',
ax25_init(&hax25, (uint8_t *) dest_addr, '1', (uint8_t *) src_addr, '1',
AX25_PREAMBLE_LEN,
AX25_POSTAMBLE_LEN);
@ -211,16 +229,11 @@ int main(int argc, char *argv[]) {
char header_str[] = "\x03\xf0hi hi ";
strcpy(str, header_str);
// printf("%s-1>CQ-1:hi hi ", CALLSIGN);
printf("%s-1>%s-1:hi hi ", (uint8_t *)src_addr, (uint8_t *)dest_addr);
int channel;
for (channel = 1; channel < 7; channel++) {
#ifdef DEBUG_LOGGING
printf("%d %d %d %d \n", tlm[channel][1], tlm[channel][2], tlm[channel][3], tlm[channel][4]);
#endif
sprintf(tlm_str, "%d%d%d %d%d%d %d%d%d %d%d%d ",
channel, upper_digit(tlm[channel][1]), lower_digit(tlm[channel][1]),
channel, upper_digit(tlm[channel][2]), lower_digit(tlm[channel][2]),
@ -229,33 +242,10 @@ int main(int argc, char *argv[]) {
printf("%s",tlm_str);
strcat(str, tlm_str);
}
if (arduinoI2C > 0) { /* Read Arduino payload */
for(int reg = 0; reg < 4; reg++) {
sprintf(tlm_str, " %04x",wiringPiI2CReadReg16(arduinoI2C,reg));
#ifdef DEBUG_LOGGING
printf("%s \n",tlm_str);
#endif
strcat(str,tlm_str); /* Append payload telemetry */
printf("%s",tlm_str);
usleep(100000);
}
}
printf("\n");
digitalWrite (0, LOW);
/*
char cmdbuffer[1000];
if (charging) {
FILE* file1 = popen("/home/pi/mopower/mpcmd LED_STAT=1", "r");
fgets(cmdbuffer, 999, file1);
pclose(file1);
// printf("LED state: %s\n", cmdbuffer);
}
*/
#ifdef DEBUG_LOGGING
fprintf(stderr,"INFO: Transmitting X.25 packet\n");
#endif
@ -271,13 +261,6 @@ char cmdbuffer[1000];
ax5043_wait_for_transmit();
digitalWrite (0, HIGH);
/*
FILE* file2 = popen("/home/pi/mopower/mpcmd LED_STAT=0", "r");
fgets(cmdbuffer, 999, file2);
pclose(file2);
// printf("LED state: %s\n", cmdbuffer);
*/
if (ret) {
fprintf(stderr,
"ERROR: Failed to transmit entire AX.25 frame with error code %d\n",
@ -327,85 +310,40 @@ int upper_digit(int number) {
}
int get_tlm(int tlm[][5]) {
// Reading I2C voltage and current sensors
char cmdbuffer[1000];
FILE* file = popen("sudo python /home/pi/CubeSatSim/python/readcurrent.py 2>&1", "r");
fgets(cmdbuffer, 999, file);
pclose(file);
#ifdef DEBUG_LOGGING
fprintf(stderr,"I2C Sensor data: %s\n", cmdbuffer);
#endif
char ina219[16][20]; // voltage, currents, and power from the INA219 current sensors x4a, x40, x41, x44, and x45.
int i = 0;
char * data2 = strtok (cmdbuffer," ");
while (data2 != NULL) {
strcpy(ina219[i], data2);
// Reading I2C voltage and current sensors
int count;
for (count = 0; count < 8; count++)
{
reading[count] = read_sensor_data(sensor[count]);
#ifdef DEBUG_LOGGING
printf ("ina219[%d]=%s\n",i,ina219[i]);
printf("Read sensor[%d] % 4.2fV % 6.1fmA % 6.1fmW \n",
count, reading[count].voltage, reading[count].current, reading[count].power);
#endif
data2 = strtok (NULL, " ");
i++;
}
// read i2c current sensors //
double current = 0, power = 0, y_current = 0, y_power = 0, z_current = 0, z_power = 0;
if (x_fd != -1) {
wiringPiI2CWriteReg16(x_fd, INA219_REG_CALIBRATION, x_calValue);
wiringPiI2CWriteReg16(x_fd, INA219_REG_CONFIG, config);
wiringPiI2CWriteReg16(x_fd, INA219_REG_CALIBRATION, x_calValue);
current = wiringPiI2CReadReg16(x_fd, INA219_REG_CURRENT) / x_currentDivider;
power = wiringPiI2CReadReg16(x_fd, INA219_REG_POWER) * x_powerMultiplier;
wiringPiI2CWriteReg16(y_fd, INA219_REG_CALIBRATION, x_calValue);
wiringPiI2CWriteReg16(y_fd, INA219_REG_CONFIG, config);
wiringPiI2CWriteReg16(y_fd, INA219_REG_CALIBRATION, x_calValue);
y_current = wiringPiI2CReadReg16(y_fd, INA219_REG_CURRENT) / x_currentDivider;
y_power = wiringPiI2CReadReg16(y_fd, INA219_REG_POWER) * x_powerMultiplier;
wiringPiI2CWriteReg16(z_fd, INA219_REG_CALIBRATION, x_calValue);
wiringPiI2CWriteReg16(z_fd, INA219_REG_CONFIG, config);
wiringPiI2CWriteReg16(z_fd, INA219_REG_CALIBRATION, x_calValue);
z_current = wiringPiI2CReadReg16(z_fd, INA219_REG_CURRENT) / x_currentDivider;
z_power = wiringPiI2CReadReg16(z_fd, INA219_REG_POWER) * x_powerMultiplier;
}
#ifdef DEBUG_LOGGING
printf("-X 0x40 current %4.2f power %4.2f -Y 0x41 current %4.2f power %4.2f -Z 0x44 current %4.2f power %4.2f \n",
current,
power,
y_current,
y_power,
z_current,
z_power);
printf("1B: ina219[%d]: %s val: %f \n", SENSOR_40 + CURRENT, ina219[SENSOR_40 + CURRENT], strtof(ina219[SENSOR_40 + CURRENT], NULL));
#endif
tlm[1][A] = (int)(strtof(ina219[SENSOR_4A + CURRENT], NULL) / 15 + 0.5) % 100; // Current of 5V supply to Pi
tlm[1][B] = (int) (99.5 - strtof(ina219[SENSOR_40 + CURRENT], NULL)/10) % 100; // +X current [4]
tlm[1][C] = (int) (99.5 - current/10) % 100; // X- current [10]
tlm[1][D] = (int) (99.5 - strtof(ina219[SENSOR_41 + CURRENT], NULL)/10) % 100; // +Y current [7]
tlm[2][A] = (int) (99.5 - y_current/10) % 100; // -Y current [10]
tlm[2][B] = (int) (99.5 - strtof(ina219[SENSOR_44 + CURRENT], NULL)/10) % 100; // +Z current [10] // was 70/2m transponder power, AO-7 didn't have a Z panel
tlm[2][C] = (int) (99.5 - z_current/10) % 100; // -Z current (was timestamp)
// tlm[2][C] = (int)((time(NULL) - timestamp) / 15) % 100;
tlm[2][D] = (int)(50.5 + strtof(ina219[SENSOR_45 + CURRENT], NULL)/10.0) % 100; // NiMH Battery current
tlm[3][A] = abs((int)((strtof(ina219[SENSOR_45 + VOLTAGE], NULL) * 10) - 65.5) % 100);
tlm[3][B] = (int)(strtof(ina219[SENSOR_4A + VOLTAGE], NULL) * 10.0) % 100; // 5V supply to Pi
if (tempSensor != -1) {
int tempValue = wiringPiI2CReadReg16(tempSensor, 0);
#ifdef DEBUG_LOGGING
printf("Temp Sensor Read: %x\n", tempValue);
#endif
tlm[1][A] = (int)(reading[BUS].voltage /15.0 + 0.5) % 100; // Current of 5V supply to Pi
tlm[1][B] = (int) (99.5 - reading[PLUS_X].current/10.0) % 100; // +X current [4]
tlm[1][C] = (int) (99.5 - reading[MINUS_X].current/10.0) % 100; // X- current [10]
tlm[1][D] = (int) (99.5 - reading[PLUS_Y].current/10.0) % 100; // +Y current [7]
tlm[2][A] = (int) (99.5 - reading[MINUS_Y].current/10.0) % 100; // -Y current [10]
tlm[2][B] = (int) (99.5 - reading[PLUS_Z].current/10.0) % 100; // +Z current [10] // was 70/2m transponder power, AO-7 didn't have a Z panel
tlm[2][C] = (int) (99.5 - reading[MINUS_Z].current/10.0) % 100; // -Z current (was timestamp)
tlm[2][D] = (int)(50.5 + reading[BAT].current/10.0) % 100; // NiMH Battery current
tlm[3][A] = abs((int)((reading[BAT].voltage * 10.0) - 65.5) % 100);
tlm[3][B] = (int)(reading[BUS].voltage * 10.0) % 100; // 5V supply to Pi
if (tempSensor.fd != OFF) {
int tempValue = wiringPiI2CReadReg16(tempSensor.fd, 0);
uint8_t upper = (uint8_t) (tempValue >> 8);
uint8_t lower = (uint8_t) (tempValue & 0xff);
float temp = (float)lower + ((float)upper / 0x100);
#ifdef DEBUG_LOGGING
printf("Temp Sensor Read: %6.1f\n", temp);
#endif
tlm[4][A] = (int)((95.8 - temp)/1.48 + 0.5) % 100;
}
@ -414,9 +352,11 @@ int get_tlm(int tlm[][5]) {
double cpuTemp;
fscanf (cpuTempSensor, "%lf", &cpuTemp);
cpuTemp /= 1000;
#ifdef DEBUG_LOGGING
printf("CPU Temp Read: %6.1f\n", cpuTemp);
#endif
tlm[4][B] = (int)((95.8 - cpuTemp)/1.48 + 0.5) % 100;
fclose (cpuTempSensor);
}
@ -437,3 +377,12 @@ int get_tlm(int tlm[][5]) {
return 0;
}
int twosToInt(int val,int len) { // Convert twos compliment to integer
// from https://www.raspberrypi.org/forums/viewtopic.php?t=55815
if(val & (1 << (len - 1)))
val = val - (1 << len);
return(val);
}

@ -1,85 +0,0 @@
/*
* A sample application transmitting AFSK at 1200 baud
*
* Portions Copyright (C) 2018 Jonathan Brandenburg
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "status.h"
#include "ax5043.h"
#include "ax25.h"
#include "spi/ax5043spi.h"
ax5043_conf_t hax5043;
ax25_conf_t hax25;
static void init_rf();
int main(void) {
setSpiChannel(SPI_CHANNEL);
setSpiSpeed(SPI_SPEED);
initializeSpi();
init_rf();
ax25_init(&hax25, (uint8_t *) "CQ", '2', (uint8_t *) "DX", '2',
AX25_PREAMBLE_LEN,
AX25_POSTAMBLE_LEN);
int ret;
uint8_t data[1024];
// 0x03 is a UI frame
// 0x0F is no Level 3 protocol
const char *str = "\x03\x0fThis is an AX.25 Packet from CubeSatSim!!!";
/* Infinite loop */
for (;;) {
sleep(2);
printf("INFO: Transmitting a packet\n");
memcpy(data, str, strnlen(str, 256));
ret = ax25_tx_frame(&hax25, &hax5043, data, strnlen(str, 256));
if (ret) {
fprintf(stderr,
"ERROR: Failed to transmit AX.25 frame with error code %d\n",
ret);
exit(EXIT_FAILURE);
}
ax5043_wait_for_transmit();
if (ret) {
fprintf(stderr,
"ERROR: Failed to transmit entire AX.25 frame with error code %d\n",
ret);
exit(EXIT_FAILURE);
}
}
return 0;
}
static void init_rf() {
int ret;
ret = ax5043_init(&hax5043, XTAL_FREQ_HZ, VCO_INTERNAL);
if (ret != PQWS_SUCCESS) {
fprintf(stderr,
"ERROR: Failed to initialize AX5043 with error code %d\n", ret);
exit(EXIT_FAILURE);
}
}

@ -0,0 +1,232 @@
/*
* Generates telemetry for CubeSat Simulator
*
* Copyright Alan B. Johnston
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* INA219 Raspberry Pi wiringPi code is based on Adafruit Arduino wire code
* from https://github.com/adafruit/Adafruit_INA219.
*/
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "status.h"
#include "ax5043.h"
#include "ax25.h"
#include "spi/ax5043spi.h"
#include <wiringPiI2C.h>
#include <wiringPi.h>
#include <time.h>
#include <math.h>
#include "../Adafruit_INA219/Adafruit_INA219.h" // From Adafruit INA219 library for Arduino
#define A 1
#define B 2
#define C 3
#define D 4
#define PLUS_X 0
#define PLUS_Y 1
#define PLUS_Z 2
#define BAT 3
#define MINUS_X 4
#define MINUS_Y 5
#define MINUS_Z 6
#define BUS 7
#define OFF -1
int twosToInt(int val, int len);
struct SensorConfig {
int fd;
uint16_t config;
int calValue;
int powerMultiplier;
int currentDivider;
};
struct SensorData {
double current;
double voltage;
double power;
};
/**
* @brief Read the data from one of the i2c current sensors.
*
* Reads the current data from the requested i2c current sensor configuration and
* stores it into a SensorData struct. An invalid file descriptor (i.e. less than zero)
* results in a SensorData struct being returned that has both its #current and #power members
* set to NAN.
*
* @param sensor A structure containing sensor configuration including the file descriptor.
* @return struct SensorData A struct that contains the current, voltage, and power readings
* from the requested sensor.
*/
struct SensorData read_sensor_data(struct SensorConfig sensor) {
struct SensorData data = {
.current = NAN,
.voltage = NAN,
.power = NAN };
if (sensor.fd < 0) {
return data;
}
// doesn't read negative currents accurately, shows -0.1mA
wiringPiI2CWriteReg16(sensor.fd, INA219_REG_CALIBRATION, sensor.calValue);
wiringPiI2CWriteReg16(sensor.fd, INA219_REG_CONFIG, sensor.config);
wiringPiI2CWriteReg16(sensor.fd, INA219_REG_CALIBRATION, sensor.calValue);
int value = wiringPiI2CReadReg16(sensor.fd, INA219_REG_CURRENT);
data.current = (float) twosToInt(value, 16) / (float) sensor.currentDivider;
wiringPiI2CWrite(sensor.fd, INA219_REG_BUSVOLTAGE);
delay(1); // Max 12-bit conversion time is 586us per sample
value = (wiringPiI2CRead(sensor.fd) << 8 ) | wiringPiI2CRead (sensor.fd);
data.voltage = ((float)(value >> 3) * 4) / 1000;
// power has very low resolution, seems to step in 512mW values
data.power = (float) wiringPiI2CReadReg16(sensor.fd, INA219_REG_POWER) * (float) sensor.powerMultiplier;
return data;
}
/**
* @brief Configures an i2c current sensor.
*
* Calculates the configuration values of the i2c sensor so that
* current, voltage, and power can be read using read_sensor_data.
* Supports 16V 400mA and 16V 2.0A settings.
*
* @param sensor A file descriptor that can be used to read from the sensor.
* @param milliAmps The mA configuration, either 400mA or 2A are supported.
* @return struct SensorConfig A struct that contains the configuraton of the sensor.
*/
//struct SensorConfig config_sensor(int sensor, int milliAmps) {
struct SensorConfig config_sensor(char *bus, int address, int milliAmps) {
struct SensorConfig data;
if (access(bus, W_OK | R_OK) < 0) { // Test if I2C Bus is missing
printf("ERROR: %s bus not present \n", bus);
data.fd = OFF;
return (data);
}
data.fd = wiringPiI2CSetupInterface(bus, address);
data.config = INA219_CONFIG_BVOLTAGERANGE_32V |
INA219_CONFIG_GAIN_1_40MV |
INA219_CONFIG_BADCRES_12BIT |
INA219_CONFIG_SADCRES_12BIT_1S_532US |
INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS;
if (milliAmps == 400) { // INA219 16V 400mA configuration
data.calValue = 8192;
data.powerMultiplier = 1;
data.currentDivider = 20; // 40; in Adafruit config
}
else { // INA219 16V 2A configuration
data.calValue = 40960;
data.powerMultiplier = 2;
data.currentDivider = 10; // 20; in Adafruit config
}
//#ifdef DEBUG_LOGGING
// printf("Sensor %s %x configuration: %d %d %d %d %d\n", bus, address, data.fd,
// data.config, data.calValue, data.currentDivider, data.powerMultiplier);
printf("Sensor %s %x | ", bus, address);
//#endif
return data;
}
struct SensorConfig sensorV;
struct SensorData readingV;
struct SensorConfig tempSensor;
int main(int argc, char *argv[]) {
if (argc > 1) {
;
}
wiringPiSetup ();
printf("\n");
sensorV = config_sensor("/dev/i2c-1", 0x40, 400);
readingV = read_sensor_data(sensorV);
printf("+X | sensor[%d] % 4.2fV % 6.1fmA % 6.1fmW \n",
PLUS_X, readingV.voltage, readingV.current, readingV.power);
sensorV = config_sensor("/dev/i2c-1", 0x41, 400);
readingV = read_sensor_data(sensorV);
printf("+Y | sensor[%d] % 4.2fV % 6.1fmA % 6.1fmW \n",
PLUS_Y, readingV.voltage, readingV.current, readingV.power);
sensorV = config_sensor("/dev/i2c-1", 0x44, 400);
readingV = read_sensor_data(sensorV);
printf("+Z | sensor[%d] % 4.2fV % 6.1fmA % 6.1fmW \n",
PLUS_Z, readingV.voltage, readingV.current, readingV.power);
sensorV = config_sensor("/dev/i2c-0", 0x40, 400);
readingV = read_sensor_data(sensorV);
printf("-X | sensor[%d] % 4.2fV % 6.1fmA % 6.1fmW \n",
MINUS_X, readingV.voltage, readingV.current, readingV.power);
sensorV = config_sensor("/dev/i2c-0", 0x41, 400);
readingV = read_sensor_data(sensorV);
printf("-Y | sensor[%d] % 4.2fV % 6.1fmA % 6.1fmW \n",
MINUS_Y, readingV.voltage, readingV.current, readingV.power);
sensorV = config_sensor("/dev/i2c-0", 0x44, 400);
readingV = read_sensor_data(sensorV);
printf("-Z | sensor[%d] % 4.2fV % 6.1fmA % 6.1fmW \n",
MINUS_Z, readingV.voltage, readingV.current, readingV.power);
sensorV = config_sensor("/dev/i2c-1", 0x45, 400);
readingV = read_sensor_data(sensorV);
printf("Bat | sensor[%d] % 4.2fV % 6.1fmA % 6.1fmW \n",
BAT, readingV.voltage, readingV.current, readingV.power);
sensorV = config_sensor("/dev/i2c-1", 0x4a, 2000);
readingV = read_sensor_data(sensorV);
printf("Bus | sensor[%d] % 4.2fV % 6.1fmA % 6.1fmW \n",
BUS, readingV.voltage, readingV.current, readingV.power);
sensorV = config_sensor("/dev/i2c-3", 0x48, 0);
if (sensorV.fd != OFF) {
int tempValue = wiringPiI2CReadReg16(sensorV.fd, 0);
uint8_t upper = (uint8_t) (tempValue >> 8);
uint8_t lower = (uint8_t) (tempValue & 0xff);
float temp = (float)lower + ((float)upper / 0x100);
printf("T | % 4.1f C \n", temp);
}
printf("\n\n");
return 0;
}
int twosToInt(int val,int len) { // Convert twos compliment to integer
// from https://www.raspberrypi.org/forums/viewtopic.php?t=55815
if(val & (1 << (len - 1)))
val = val - (1 << len);
return(val);
}
Loading…
Cancel
Save

Powered by TurnKey Linux.