UoS³ Flight Computer Firmware
 All Data Structures Files Functions Groups Pages
i2cpythontest.c
1 
2 // i2c IMU functionality test
3 //
4 // Suzanna Lucarotti (c) 11/8/2017
5 //
6 // for use with the UoS3 Cubesat
7 //
8 // derived from blinky and Ti's i2c examples and MPU9205 datasheets
9 //
10 // this version alters the format to transmit for a python automated plotter
11 
12 // packet format is 0xFE (frame start), then Acc data (6 bytes x,y,z) , Gyr data (6bytes x,y,z,), temp (2bytes), Magnetometer (6bytes x,y,z)
13 // all data is big endian
14 
15 
16 #include "../firmware.h"
17 
18 #include "inc/hw_i2c.h"
19 #include "inc/hw_memmap.h"
20 #include "inc/hw_types.h"
21 
22 #include "driverlib/gpio.h"
23 #include "driverlib/i2c.h"
24 #include "driverlib/pin_map.h"
25 #include "driverlib/sysctl.h"
26 
27 #include <stdlib.h>
28 #include <stdarg.h>
29 
30 #define DEBUG_SERIAL UART_CAMERA // this is the serial port debug messages will come through (UART_CAMERA or UART_GNSS)
31 #define GPS_SERIAL UART_GNSS
32 #define CAM_SERIAL UART_CAMERA
33 
34 #define DEBUG_SERIAL GPS_SERIAL
35 
36  // the useful hardware constants (only used here so not moved away as yet)
37 
38 #define SLAVE_ADDRESS 0x68 // this is the MPU-9250A i2c address %1011000
39 
40 // MPU 9250 registers
41 
42 #define MPU_CONFIG 26
43 #define MPU_GYRO_CONFIG 27
44 #define MPU_ACCEL_CONFIG 28
45 #define MPU_ACCEL_XOUT 59
46 #define MPU_ACCEL_YOUT 61
47 #define MPU_ACCEL_ZOUT 63
48 #define MPU_TEMP_OUT 65
49 #define MPU_GYRO_XOUT 67
50 #define MPU_GYRO_YOUT 69
51 #define MPU_GYRO_ZOUT 71
52 #define MPU_WHO_AM_I 117
53 #define MPU_INT_BYPASS_ENABLE 55
54 
55 
56 // Wrappers for printing to serial port - always to the one specified as output, placed here close to code for clarity
57 
58 #define STRING_BUFFER_LENGTH 20 // rough hack for testing
59 
60 static char string_buffer[STRING_BUFFER_LENGTH];
61 static char string_buffer2[STRING_BUFFER_LENGTH];
62 
63 static void UART_putnum(unsigned int serialport,signed long x)
64  {
65  itoa(abs(x),string_buffer,16); // 16 for hex, 10 for decimal
66  unsigned int len=strlen(string_buffer);
67  unsigned int targetlen=6-len;
68  strcpy(string_buffer2,"+00000");
69  strcpy(string_buffer2+targetlen,string_buffer);
70  if (x<0) string_buffer2[0]='-';
71  UART_puts(serialport,string_buffer2);
72 }
73 
74 static void UART_putstr(unsigned int serialport, char *s1,signed long x, char *s2)
75  {
76  if (s1!=NULL) UART_puts(serialport,s1);
77  UART_putnum(serialport,x);
78  if (s2!=NULL) UART_puts(serialport,s2);
79  }
80 
81 #define DISP3(x,y,z) UART_putstr(DEBUG_SERIAL,x,y,z); // x and z are strings, y is a number shown as signed base10 16bit
82 #define DISP2(y,z) UART_putstr(DEBUG_SERIAL,NULL,y,z);
83 #define DISP1(x) UART_puts(DEBUG_SERIAL,x);
84 #define DISP(x) UART_putc(DEBUG_SERIAL,x);
85 #define DISPW(x) UART_putc(DEBUG_SERIAL,x&0xff);UART_putc(DEBUG_SERIAL,x>>8);
86 
88  // the actual main code
90 
91 int main(void)
92 {
93 
94  Board_init(); // start the board
95  InitI2C2(); // initialise correct interface on processor
96  setupwatchdoginterrupt();
97 
98  UART_init(DEBUG_SERIAL, 115200); //DISP1("\n\n\r I2C Satellite I2C IMU test.\n")
99 
100  // start the console, print bootup message (below)
101 
102  #define MAG_PASS_THROUGH_I2C_ADDR 12
103 
104  #define MAG_HXL 3
105  #define MAG_HYL 5
106  #define MAG_HZL 7 // offsets in magnetometer, note little endian, so need to be read opposite way round
107  #define MAG_CNTL1 10 // Magnetometer control register
108  #define MAG_STA1 2 // read only gives flags at 1 for DRDY and 2 for DOR (data ready and overload), used in read cycle
109 
110 // enable magnetometer to appear separately I2C by commanding MPU chip
111 
112  char i2cstring[3]; // static buffer for i2c calls here
113  i2cstring[0]=MPU_INT_BYPASS_ENABLE; // int pin /bypass enable configuration
114  char i2cstatus=I2CReceive(SLAVE_ADDRESS,MPU_INT_BYPASS_ENABLE,I2C2_BASE);
115  i2cstring[1]=i2cstatus | MPU_INT_BYPASS_ENABLE; // flag bypass on
116  i2cstring[3]=0; // null terminated string
117  I2CSendString(SLAVE_ADDRESS, i2cstring,I2C2_BASE); // turn on bypass to Magnetometer so visible on I2C
118 
119 // setup magnetometer
120 
121  i2cstring[0]=MAG_CNTL1;
122  i2cstring[2]=0;
123  i2cstring[1]=0; // set mode to zero before changing mode
124  I2CSendString(MAG_PASS_THROUGH_I2C_ADDR, i2cstring,I2C2_BASE); // set Magnetometer to safe mode before mode change
125  i2cstring[1]=1 | 0; // continuous (16hz) mode with 14bit range
126  I2CSendString(MAG_PASS_THROUGH_I2C_ADDR, i2cstring,I2C2_BASE); // set Magnetometer to continuous shot mode with 16bit range, single shot needs updating and has delay
127 
128  char mag_id=I2CReceive(MAG_PASS_THROUGH_I2C_ADDR,0,I2C2_BASE); // magnetometer ID (hopefully)
129 
130 //DISP3("\r I2Cstatus old: ",i2cstatus,"\n")
131 //DISP3("\r I2Cstatus new (After enabling passthrough for Magnetometer): ",I2CReceive(SLAVE_ADDRESS,55),"\n")
132 //DISP3("\r Magnetometer ID (test, should equal 72 if found): ",mag_id,"\n")
133 
134 signed short acc_x,acc_y,acc_z,gyr_x,gyr_y,gyr_z,mag_x,mag_y,mag_z,temp;
135 
136 // some macros to simplify repeated I2c calls - deliberately kept near where used
137 #define MPUGET(x) I2CReceive16(SLAVE_ADDRESS,x,I2C2_BASE); // wrapper for I2C call to MPU
138 #define MAGGET(x) I2CReceive16r(MAG_PASS_THROUGH_I2C_ADDR, x,I2C2_BASE); // wrapper for I2C call to Magnetometer
139 
140 DISP1("\n\n\n\rI2C IMU test - python compressed data version (use I2Ctest for human readable):\n\n")
141 wait(1000); // so can see this if monitoring in terminal
142 
143  while(1) // infinite loop
144  {
145  acc_x=MPUGET(MPU_ACCEL_XOUT) acc_y=MPUGET( MPU_ACCEL_YOUT) acc_z=MPUGET(MPU_ACCEL_ZOUT)
146  gyr_x=MPUGET(MPU_GYRO_XOUT) gyr_y=MPUGET(MPU_GYRO_YOUT) gyr_z=MPUGET(MPU_GYRO_ZOUT)
147  temp=MPUGET(MPU_TEMP_OUT)
148 
149  // magnetometer should be in power down mode with data ready, if not wait for it
150  while ((I2CReceive(MAG_PASS_THROUGH_I2C_ADDR,MAG_STA1,I2C2_BASE)&1)!=1) {}
151  mag_x=MAGGET(MAG_HXL) mag_y=MAGGET(MAG_HYL) mag_z=MAGGET(MAG_HZL)
152 
153  I2CSendString(MAG_PASS_THROUGH_I2C_ADDR, i2cstring,I2C2_BASE); // prepare magnetometer for next call (delay, so give lead in
154 
155  // now send the packets for python
156 
157  DISP('@') // frame start
158  DISPW(acc_x) DISPW(acc_y) DISPW(acc_z)
159  DISPW(gyr_x) DISPW(gyr_y) DISPW(gyr_z)
160  DISPW(mag_x) DISPW(mag_y) DISPW(mag_z)
161  // DISPW(20000) DISPW(-20000) DISPW (10000)
162  DISPW(temp)
163 
164 }
165 }
166 
167 
void UART_init(uint8_t uart_num, uint32_t baudrate)
Definition: uart.c:78
int main(void)
Runs all module tests.
Definition: test.c:19
void UART_puts(uint8_t uart_num, char *str)
Definition: uart.c:129
void Board_init(void)
Definition: board.c:13