可以测试 SPI 通信 winhout 外部模块
Is possible to test SPI communication winhout external module
我有一个非常简单的问题,我想...我正在使用两个 SPI 通信(一个 classis SPI 和第二个 int SPI)在 SAMD21 板上编程,我认为 int SPI 无法正常工作。如果我连接一些传感器,它不会向串行监视器打印任何内容。我很确定,我的代码没问题,但可能会有一些错误...
所以我需要知道,是否有某种方法可以测试 SPI winhout 将外部设备连接到电路板。请不要讨厌代码太长,我使用的 SPI 传感器代码标有“//SPI”。
PS: 抱歉删除了SMUART和MICS6814的测量校准功能,只用了30000字。完整代码在这里:https://mega.nz/file/2QxG0ayZ#4UpEU17ogXnm2NK22zAowlDDRrXzksPzzs05zbuq23o
#include <Adafruit_BME280.h> // include Adafruit BME280 library
#include <Adafruit_INA219.h> // include INA219
#include <SD.h> // include Arduino SD library
#include "Open_Cansat_GPS.h"
#include <RTCZero.h>
//include our new sensors
#include <MICS6814.h>
#include <MICS-VZ-89TE.h>
#include "MQ131.h"
#include <Wire.h>
#include <SPI.h>
#include "RFM69.h" // include RFM69 library
// Local
#define PC_BAUDRATE 115200
#define MS_DELAY 0 // Number of milliseconds between data sending and LED signalization
#define LED_DELAY 100
#define Serial SerialUSB
RTCZero rtc;
// RFM69
#define NETWORKID 0 // Must be the same for all nodes (0 to 255)
#define MYNODEID 1 // My node ID (0 to 255)
#define TONODEID 2 // Destination node ID (0 to 254, 255 = broadcast)
#define FREQUENCY RF69_433MHZ // Frequency set up
#define FREQUENCYSPECIFIC 433000000 // Should be value in Hz, now 433 Mhz will be set
#define CHIP_SELECT_PIN 43 //radio chip select
#define INTERUP_PIN 9 //radio interrupt
// BME280 SETTING
#define BME280_ADDRESS_OPEN_CANSAT 0x77
#define SEALEVELPRESSURE_HPA 1013.25
//define our sensor pins
//MICS6814
#define PIN_CO 0
#define PIN_NO2 0
#define PIN_NH3 0
#define MICS6814Pin 6
//OZONE2CLICK
const byte pinSS = 2;
const byte pinRDY = 12;
const byte pinSCK = 13;
const byte O2Pin = 10;
//SMUART
bool flag1 = false;
bool flag2 = false;
byte rxData[30];
byte one, two;
#define DcPin 8
//MICSVZ89TE
#define MICSVZ89TEPin 7
int datas [7];
bool MICS_status;
int MICS_voc;
int MICS_eqco2;
//PHASES
float CurrentTime;
const byte day = 17;
const byte month = 11;
const byte year = 15;
MICS6814 gas(PIN_CO, PIN_NO2, PIN_NH3);
long accelX, accelY, accelZ;
float gForceX, gForceY, gForceZ;
long gyroX, gyroY, gyroZ;
float rotX, rotY, rotZ;
#define sd_cs_pin 35 // set SD's chip select pin (according to the circuit)
RFM69 radio(CHIP_SELECT_PIN, INTERUP_PIN, true);
typedef struct
{
int16_t messageId;
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t sec;
float longitude;
float latitude;
uint8_t num_of_satelites;
float temperature;
float pressure;
float altitude;
float humidity_bme280;
float voltage_shunt;
float voltage_bus;
float current_mA;
float voltage_load;
int16_t rssi;
} messageOut;
messageOut cansatdata; //create the struct variable
Adafruit_BME280 bme;
Adafruit_INA219 ina219(0x40);
OpenCansatGPS gps;
File file; // SD library variable
// LEDS
#define D13_led_pin 42 // D13 LED
#define M_led_pin 36 // MLED
// Local variables
int idCounter = 1;
bool isBmeOk = true;
bool isSdOk = true;
bool isRadioOk = true;
bool isGpsConnected = true;
// My variables
float NH3Data;
float COData;
float NO2Data;
float PPMO2;
float PPBO2;
float MGM3O2;
float UGM3O2;
float SSmoke1;
float SSmoke2;
float SSmoke3;
float ESmoke1;
float ESmoke2;
float ESmoke3;
int DataCounter = 0;
void RTCBegin ()
{
rtc.begin();
}
void RTCSleep ()
{
digitalWrite(O2Pin, LOW);
digitalWrite(MICS6814Pin, LOW);
digitalWrite(MICSVZ89TEPin, LOW);
digitalWrite(DcPin, LOW);
digitalWrite(D13_led_pin, LOW);
digitalWrite(M_led_pin, LOW);
GyroscopeSleep();
byte seconds = 0;
byte minutes = 00;
byte hours = 00;
rtc.setTime(hours, minutes, seconds);
rtc.setDate(day, month, year);
rtc.setAlarmTime(00, 00, 10);
rtc.enableAlarm(rtc.MATCH_HHMMSS);
rtc.standbyMode();
TerrestrialPhase();
// Sleep until next alarm match
}
//SPI
void OZONE2CLICKCalibrate ()
{
Serial.println("2");
//MQ131.begin(pinSS, pinRDY, O2Pin, LOW_CONCENTRATION, 10000); //(int _pinCS, int _pinRDY, int _pinPower, MQ131Model _model, int _RL)
Serial.println("99");
Serial.println("Calibration in progress...");
MQ131.calibrate();
Serial.println("Calibration done!");
Serial.print("R0 = ");
Serial.print(MQ131.getR0());
Serial.println(" Ohms");
Serial.print("Time to heat = ");
Serial.print(MQ131.getTimeToRead());
Serial.println(" s");
}
void OZONE2CLICKMeasure ()
{
Serial.println("Sampling...");
MQ131.sample();
Serial.print("Concentration O3 : ");
PPMO2 = MQ131.getO3(PPM);
Serial.print(PPMO2);
Serial.println(" ppm");
Serial.print("Concentration O3 : ");
PPBO2 = MQ131.getO3(PPB);
Serial.print(PPBO2);
Serial.println(" ppb");
Serial.print("Concentration O3 : ");
MGM3O2 = MQ131.getO3(MG_M3);
Serial.print(MGM3O2);
Serial.println(" mg/m3");
Serial.print("Concentration O3 : ");
UGM3O2 = MQ131.getO3(UG_M3);
Serial.print(UGM3O2);
Serial.println(" ug/m3");
}
//SPI
void MICSVZ89TEMeasure()
{
delay(5000);
MICS_VZ_89TE myMICS;
MICS_status = myMICS.begin();
myMICS.readSensor();
MICS_eqco2 = myMICS.getCO2();
MICS_voc = myMICS.getVOC();
Serial.print("MICS VOC PPB: ");
Serial.println(MICS_voc);
Serial.print("MICS CO2 PPM: ");
Serial.println(MICS_eqco2);
delay(1000);
}
void GyroscopeTurnOn()
{
Wire.begin();
setupMPU();
}
void GyroscopeMeasure() {
recordAccelRegisters();
recordGyroRegisters();
printData();
}
void setupMPU(){
Wire.beginTransmission(0b1101000); //This is the I2C address of the MPU (b1101000/b1101001 for AC0 low/high datasheet sec. 9.2)
Wire.write(0x6B); //Accessing the register 6B - Power Management (Sec. 4.28)
Wire.write(0b00000000); //Setting SLEEP register to 0. (Required; see Note on p. 9)
Wire.endTransmission();
Wire.beginTransmission(0b1101000); //I2C address of the MPU
Wire.write(0x1B); //Accessing the register 1B - Gyroscope Configuration (Sec. 4.4)
Wire.write(0x00000000); //Setting the gyro to full scale +/- 250deg./s
Wire.endTransmission();
Wire.beginTransmission(0b1101000); //I2C address of the MPU
Wire.write(0x1C); //Accessing the register 1C - Acccelerometer Configuration (Sec. 4.5)
Wire.write(0b00000000); //Setting the accel to +/- 2g
Wire.endTransmission();
}
void GyroscopeSleep(){
Wire.beginTransmission(0b1101000); //This is the I2C address of the MPU (b1101000/b1101001 for AC0 low/high datasheet sec. 9.2)
Wire.write(0x6B); //Accessing the register 6B - Power Management (Sec. 4.28)
Wire.write(0b01000000); //Setting SLEEP register to 0. (Required; see Note on p. 9)
Wire.endTransmission();
}
void recordAccelRegisters() {
Wire.beginTransmission(0b1101000); //I2C address of the MPU
Wire.write(0x3B); //Starting register for Accel Readings
Wire.endTransmission();
Wire.requestFrom(0b1101000,6); //Request Accel Registers (3B - 40)
while(Wire.available() < 6);
accelX = Wire.read()<<8|Wire.read(); //Store first two bytes into accelX
accelY = Wire.read()<<8|Wire.read(); //Store middle two bytes into accelY
accelZ = Wire.read()<<8|Wire.read(); //Store last two bytes into accelZ
processAccelData();
}
void processAccelData(){
gForceX = accelX / 16384.0;
gForceY = accelY / 16384.0;
gForceZ = accelZ / 16384.0;
}
void recordGyroRegisters() {
Wire.beginTransmission(0b1101000); //I2C address of the MPU
Wire.write(0x43); //Starting register for Gyro Readings
Wire.endTransmission();
Wire.requestFrom(0b1101000,6); //Request Gyro Registers (43 - 48)
while(Wire.available() < 6);
gyroX = Wire.read()<<8|Wire.read(); //Store first two bytes into accelX
gyroY = Wire.read()<<8|Wire.read(); //Store middle two bytes into accelY
gyroZ = Wire.read()<<8|Wire.read(); //Store last two bytes into accelZ
processGyroData();
}
void processGyroData() {
rotX = gyroX / 131.0;
rotY = gyroY / 131.0;
rotZ = gyroZ / 131.0;
}
void printData() {
Serial.print("Gyro (deg)");
Serial.print(" X=");
Serial.print(rotX);
Serial.print(" Y=");
Serial.print(rotY);
Serial.print(" Z=");
Serial.print(rotZ);
Serial.print(" Accel (g)");
Serial.print(" X=");
Serial.print(gForceX);
Serial.print(" Y=");
Serial.print(gForceY);
Serial.print(" Z=");
Serial.println(gForceZ);
}
void TerrestrialPhase()
{
Serial.println("------------------------------");
Serial.println("TERRESTRIAL PHASE IN PROGRESS");
Serial.println("------------------------------");
Serial.println(" ");
digitalWrite(DcPin, HIGH);
digitalWrite(MICS6814Pin, HIGH);
digitalWrite(MICSVZ89TEPin, HIGH);
digitalWrite(O2Pin, HIGH);
delay(2000);
MICSVZ89TEMeasure();
MICSVZ89TEMeasure();
MICSVZ89TEMeasure();
MICSVZ89TEMeasure();
MICS6814Calibrate();
MICS6814Measure();
SMUARTTurnOn();
delay(10000);
SMUARTMeasure();
delay(10000);
SMUARTMeasure();
delay(1000);
SMUARTMeasure();
delay(1000);
SMUARTMeasure();
delay(1000);
OZONE2CLICKCalibrate();
OZONE2CLICKMeasure();
SDSave();
delay(10000);
RTCBegin();
RTCSleep();
}
void LandingChecker()
{
CurrentTime = millis();
Serial.println(CurrentTime);
if (CurrentTime >= 30000)
{
Serial.println("------------------------------");
Serial.println("AIR PHASE DONE");
Serial.println("------------------------------");
Serial.println(" ");
Serial.println("------------------------------");
Serial.println("STARTING TESTING PHASE");
Serial.println("------------------------------");
Serial.println(" ");
TestingPhase1();
}
else
{
Serial.println("------------------------------");
Serial.println("AIR PHASE IN PROGRESS");
Serial.println("------------------------------");
Serial.println(" ");
}
}
void WaitingPhase()
{
digitalWrite(O2Pin, LOW);
digitalWrite(MICS6814Pin, LOW);
digitalWrite(MICSVZ89TEPin, LOW);
digitalWrite(DcPin, LOW);
digitalWrite(D13_led_pin, LOW);
digitalWrite(M_led_pin, LOW);
GyroscopeSleep();
byte seconds = 0;
byte minutes = 00;
byte hours = 00;
rtc.setTime(hours, minutes, seconds);
rtc.setDate(day, month, year);
rtc.setAlarmTime(00, 00, 10);
rtc.enableAlarm(rtc.MATCH_HHMMSS);
rtc.standbyMode();
TerrestrialPhase();
}
void TestingPhase2()
{
Serial.println("------------------------------");
Serial.println("TESTING PHASE DONE");
Serial.println("------------------------------");
Serial.println(" ");
Serial.println("------------------------------");
Serial.println("STARTING TERRESTRIAL PHASE");
Serial.println("------------------------------");
Serial.println(" ");
TerrestrialPhase();
}
void TestingPhase1()
{
if (((gForceX >= 3.60) || (gForceX <= 0.40)) && ((gForceY >= 2.9) && (gForceY <= 3.20)))
{
Serial.println("------------------------------");
Serial.println("SATELITE POSITION: VERY GOOD");
Serial.println("------------------------------");
Serial.println(" ");
TestingPhase2();
}
else if (((gForceX >= 3.30) || (gForceX <= 0.70)) && ((gForceY >= 2.9) && (gForceY <= 3.30)))
{
Serial.println("------------------------------");
Serial.println("SATELITE POSITION: GOOD");
Serial.println("------------------------------");
Serial.println(" ");
TestingPhase2();
}
else if (((gForceX >= 3) || (gForceX <= 1)) && ((gForceY >= 2.9) && (gForceY <= 4)))
{
Serial.println("------------------------------");
Serial.println("SATELITE POSITION: OK");
Serial.println("------------------------------");
Serial.println(" ");
TestingPhase2();
}
else
{
Serial.println("------------------------------");
Serial.println("SATELITE POSITION: BAD");
Serial.println("------------------------------");
Serial.println(" ");
Serial.println("------------------------------");
Serial.println("TESTING PHASE FAILED");
Serial.println("------------------------------");
Serial.println(" ");
WaitingPhase();
}
}
void SDSave()
{
while(!Serial);
if (!SD.begin(sd_cs_pin))
{
Serial.println("SD card initialization failed!");
return;
}
Serial.println("SD card initialized");
file = SD.open("data.txt", FILE_WRITE); // Open test.txt for write
// Rrite to the file and print info to serial
// print an error to the serial in case it does not succeed
if (file)
{
file.println("--------------------------");
file.println("GyKoVySAT terrestrial data");
file.println("--------------------------");
file.println("OZONE");
file.println(PPMO2);
file.print(" ppm");
file.println(PPBO2);
file.print(" ppb");
file.println(MGM3O2);
file.print(" mg/m³");
file.println("SMOKE PARTICLES STANDART");
file.println(UGM3O2);
file.print(" μg/m³");
file.println(SSmoke1);
file.print(" μg/m³");
file.println(SSmoke2);
file.print(" μg/m³");
file.println(SSmoke3);
file.println("SMOKE PARTICLES ENVIROMENTAL");
file.println(ESmoke1);
file.print(" μg/m³");
file.println(ESmoke2);
file.print(" μg/m³");
file.println(ESmoke3);
file.print(" μg/m³");
file.println("VOC");
file.println(MICS_voc);
file.print(" ppm");
file.println("CO2");
file.println(MICS_eqco2);
file.print(" ppm");
file.println("CO");
file.println(COData);
file.print(" ppm");
file.println("NO2");
file.println(NO2Data);
file.print(" ppm");
file.println("NH3");
file.println(NH3Data);
file.print(" ppm");
file.println("DATA FOR ANALYZATION");
file.println(PPMO2);
file.print(";");
file.print(PPBO2);
file.print(";");
file.print(MGM3O2);
file.print(";");
file.print(UGM3O2);
file.print(";");
file.print(SSmoke1);
file.print(";");
file.print(SSmoke2);
file.print(";");
file.print(SSmoke3);
file.print(";");
file.print(ESmoke1);
file.print(";");
file.print(ESmoke2);
file.print(";");
file.print(ESmoke3);
file.print(";");
file.print(MICS_voc);
file.print(";");
file.print(MICS_eqco2);
file.print(";");
file.print(COData);
file.print(";");
file.print(NO2Data);
file.print(";");
file.print(NH3Data);
file.print(";");
file.print(DataCounter);
file.print(";");
file.close();
DataCounter = DataCounter + 1;
}
else
{
Serial.println("Error opening data.txt for writing");
}
TerrestrialPhase();
}
void setup()
{
// wait for the Arduino serial (on your PC) to connect
// please, open the Arduino serial console (right top corner)
// note that the port may change after uploading the sketch
// COMMENT OUT FOR USAGE WITHOUT A PC!
// while(!Serial);
Serial.println("openCanSat PRO");
Serial.print("Node ");
Serial.print(MYNODEID,DEC);
Serial.println(" ready");
// begin communication with the BME280 on the previously specified address
// print an error to the serial in case the sensor is not found
if (!bme.begin(BME280_ADDRESS_OPEN_CANSAT))
{
isBmeOk = false;
Serial.println("Could not find a valid BME280 sensor, check wiring!");
return;
}
// begin communication with the INA219
ina219.begin();
// check of Gps is connected
Wire.beginTransmission(0x42); // 42 is addres of GPS
int error = Wire.endTransmission();
if (error != 0)
{
isGpsConnected = false;
}
// begin communication with gps
gps.begin();
// Uncomment when you want to see debug prints from GPS library
// gps.debugPrintOn(57600);
if(!radio.initialize(FREQUENCY, MYNODEID, NETWORKID))
{
isRadioOk = false;
Serial.println("RFM69HW initialization failed!");
}
else
{
radio.setFrequency(FREQUENCYSPECIFIC);
radio.setHighPower(true); // Always use this for RFM69HW
}
pinMode(D13_led_pin, OUTPUT);
pinMode(DcPin, OUTPUT);
pinMode(MICS6814Pin, OUTPUT);
pinMode(MICSVZ89TEPin, OUTPUT);
pinMode(O2Pin, OUTPUT);
GyroscopeTurnOn();
}
void loop()
{
cansatdata.messageId = idCounter;
GyroscopeMeasure();
LandingChecker();
Serial.println("MessageId = " + static_cast<String>(cansatdata.messageId));
cansatdata.temperature = 0;
cansatdata.pressure = 0;
cansatdata.altitude = 0;
if(isBmeOk)
{
cansatdata.temperature += bme.readTemperature();
cansatdata.pressure += bme.readPressure() / 100.0F;
cansatdata.altitude += bme.readAltitude(SEALEVELPRESSURE_HPA);
cansatdata.humidity_bme280 = bme.readHumidity();
}
Serial.println("Temperature = " + static_cast<String>(cansatdata.temperature) + " *C");
Serial.println("Pressure = " + static_cast<String>(cansatdata.pressure) + " Pa");
Serial.println("Approx altitude = " + static_cast<String>(cansatdata.altitude) + " m");
Serial.println("Humidity = " + static_cast<String>(cansatdata.humidity_bme280) + " %");
// read values from INA219 into structure
cansatdata.voltage_shunt = ina219.getShuntVoltage_mV();
cansatdata.voltage_bus = ina219.getBusVoltage_V();
cansatdata.current_mA = ina219.getCurrent_mA();
cansatdata.voltage_load = cansatdata.voltage_bus + (cansatdata.voltage_shunt / 1000);
Serial.println("Shunt Voltage: " + static_cast<String>(cansatdata.voltage_shunt) + " mV");
Serial.println("Bus Voltage: " + static_cast<String>(cansatdata.voltage_bus) + " V");
Serial.println("Current: " + static_cast<String>(cansatdata.current_mA) + " mA");
Serial.println("Load Voltage: " + static_cast<String>(cansatdata.voltage_load) + " V");
// Initialize GPS
cansatdata.year = 0;
cansatdata.month = 0 ;
cansatdata.day = 0;
cansatdata.hour = 0;
cansatdata.minute = 0;
cansatdata.sec = 0;
cansatdata.latitude = 0;
cansatdata.longitude = 0;
cansatdata.num_of_satelites = 0;
// save start time in millisec
uint32_t start = millis();
// END LED BLINK
digitalWrite(D13_led_pin, LOW);
pinMode(M_led_pin, INPUT);
// END LED BLINK
if(isGpsConnected)
{
if (gps.scan(250))
{
cansatdata.year = gps.getYear();
cansatdata.month = gps.getMonth();
cansatdata.day = gps.getDay();
cansatdata.hour = gps.getHour();
cansatdata.minute = gps.getMinute();
cansatdata.sec = gps.getSecond();
cansatdata.latitude = gps.getLat();
cansatdata.longitude = gps.getLon();
cansatdata.num_of_satelites = gps.getNumberOfSatellites();
Serial.println(String("Time to find fix: ") + (millis() - start) + String("ms"));
Serial.println(String("Datetime: ") + String(cansatdata.year) + "/"+ String(cansatdata.month) + "/"+ String(cansatdata.day) + " " + String(cansatdata.hour) + ":"+ String(cansatdata.minute) + ":"+ String(cansatdata.sec));
Serial.println(String("Lat: ") + String(cansatdata.latitude, 7));
Serial.println(String("Lon: ") + String(cansatdata.longitude, 7));
Serial.println(String("Num of sats: ") + String(cansatdata.num_of_satelites));
Serial.println();
}
else
{
Serial.println("Gps have no satelit to fix.");
}
}
// RFM69HW
cansatdata.rssi = 0;
if(isRadioOk)
{
cansatdata.rssi = radio.RSSI;
Serial.println("Signal = " + static_cast<String>(radio.RSSI));
radio.send(TONODEID, (const void*)&cansatdata, sizeof(cansatdata));
}
Serial.println();
// START LED hart beat
pinMode(M_led_pin, OUTPUT);
digitalWrite(D13_led_pin, HIGH);
digitalWrite(M_led_pin, HIGH);
// START LED hart beat
if(!isGpsConnected)
{
delay(200);
}
idCounter ++;
}
大多数 SPI 接口可以置于 'loopback' 模式,这使得代码可以轻松检查 activity 以验证 transmitted/received 数据
关于:
if (error != 0)
{
isGpsConnected = false;
}
// begin communication with gps
gps.begin();
如果没有连接 GPS,则不应尝试与 GPS 通信。建议:
if (error != 0)
{
isGpsConnected = false;
return;
}
else
{
// begin communication with gps
gps.begin();
}
我有一个非常简单的问题,我想...我正在使用两个 SPI 通信(一个 classis SPI 和第二个 int SPI)在 SAMD21 板上编程,我认为 int SPI 无法正常工作。如果我连接一些传感器,它不会向串行监视器打印任何内容。我很确定,我的代码没问题,但可能会有一些错误...
所以我需要知道,是否有某种方法可以测试 SPI winhout 将外部设备连接到电路板。请不要讨厌代码太长,我使用的 SPI 传感器代码标有“//SPI”。
PS: 抱歉删除了SMUART和MICS6814的测量校准功能,只用了30000字。完整代码在这里:https://mega.nz/file/2QxG0ayZ#4UpEU17ogXnm2NK22zAowlDDRrXzksPzzs05zbuq23o
#include <Adafruit_BME280.h> // include Adafruit BME280 library
#include <Adafruit_INA219.h> // include INA219
#include <SD.h> // include Arduino SD library
#include "Open_Cansat_GPS.h"
#include <RTCZero.h>
//include our new sensors
#include <MICS6814.h>
#include <MICS-VZ-89TE.h>
#include "MQ131.h"
#include <Wire.h>
#include <SPI.h>
#include "RFM69.h" // include RFM69 library
// Local
#define PC_BAUDRATE 115200
#define MS_DELAY 0 // Number of milliseconds between data sending and LED signalization
#define LED_DELAY 100
#define Serial SerialUSB
RTCZero rtc;
// RFM69
#define NETWORKID 0 // Must be the same for all nodes (0 to 255)
#define MYNODEID 1 // My node ID (0 to 255)
#define TONODEID 2 // Destination node ID (0 to 254, 255 = broadcast)
#define FREQUENCY RF69_433MHZ // Frequency set up
#define FREQUENCYSPECIFIC 433000000 // Should be value in Hz, now 433 Mhz will be set
#define CHIP_SELECT_PIN 43 //radio chip select
#define INTERUP_PIN 9 //radio interrupt
// BME280 SETTING
#define BME280_ADDRESS_OPEN_CANSAT 0x77
#define SEALEVELPRESSURE_HPA 1013.25
//define our sensor pins
//MICS6814
#define PIN_CO 0
#define PIN_NO2 0
#define PIN_NH3 0
#define MICS6814Pin 6
//OZONE2CLICK
const byte pinSS = 2;
const byte pinRDY = 12;
const byte pinSCK = 13;
const byte O2Pin = 10;
//SMUART
bool flag1 = false;
bool flag2 = false;
byte rxData[30];
byte one, two;
#define DcPin 8
//MICSVZ89TE
#define MICSVZ89TEPin 7
int datas [7];
bool MICS_status;
int MICS_voc;
int MICS_eqco2;
//PHASES
float CurrentTime;
const byte day = 17;
const byte month = 11;
const byte year = 15;
MICS6814 gas(PIN_CO, PIN_NO2, PIN_NH3);
long accelX, accelY, accelZ;
float gForceX, gForceY, gForceZ;
long gyroX, gyroY, gyroZ;
float rotX, rotY, rotZ;
#define sd_cs_pin 35 // set SD's chip select pin (according to the circuit)
RFM69 radio(CHIP_SELECT_PIN, INTERUP_PIN, true);
typedef struct
{
int16_t messageId;
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t sec;
float longitude;
float latitude;
uint8_t num_of_satelites;
float temperature;
float pressure;
float altitude;
float humidity_bme280;
float voltage_shunt;
float voltage_bus;
float current_mA;
float voltage_load;
int16_t rssi;
} messageOut;
messageOut cansatdata; //create the struct variable
Adafruit_BME280 bme;
Adafruit_INA219 ina219(0x40);
OpenCansatGPS gps;
File file; // SD library variable
// LEDS
#define D13_led_pin 42 // D13 LED
#define M_led_pin 36 // MLED
// Local variables
int idCounter = 1;
bool isBmeOk = true;
bool isSdOk = true;
bool isRadioOk = true;
bool isGpsConnected = true;
// My variables
float NH3Data;
float COData;
float NO2Data;
float PPMO2;
float PPBO2;
float MGM3O2;
float UGM3O2;
float SSmoke1;
float SSmoke2;
float SSmoke3;
float ESmoke1;
float ESmoke2;
float ESmoke3;
int DataCounter = 0;
void RTCBegin ()
{
rtc.begin();
}
void RTCSleep ()
{
digitalWrite(O2Pin, LOW);
digitalWrite(MICS6814Pin, LOW);
digitalWrite(MICSVZ89TEPin, LOW);
digitalWrite(DcPin, LOW);
digitalWrite(D13_led_pin, LOW);
digitalWrite(M_led_pin, LOW);
GyroscopeSleep();
byte seconds = 0;
byte minutes = 00;
byte hours = 00;
rtc.setTime(hours, minutes, seconds);
rtc.setDate(day, month, year);
rtc.setAlarmTime(00, 00, 10);
rtc.enableAlarm(rtc.MATCH_HHMMSS);
rtc.standbyMode();
TerrestrialPhase();
// Sleep until next alarm match
}
//SPI
void OZONE2CLICKCalibrate ()
{
Serial.println("2");
//MQ131.begin(pinSS, pinRDY, O2Pin, LOW_CONCENTRATION, 10000); //(int _pinCS, int _pinRDY, int _pinPower, MQ131Model _model, int _RL)
Serial.println("99");
Serial.println("Calibration in progress...");
MQ131.calibrate();
Serial.println("Calibration done!");
Serial.print("R0 = ");
Serial.print(MQ131.getR0());
Serial.println(" Ohms");
Serial.print("Time to heat = ");
Serial.print(MQ131.getTimeToRead());
Serial.println(" s");
}
void OZONE2CLICKMeasure ()
{
Serial.println("Sampling...");
MQ131.sample();
Serial.print("Concentration O3 : ");
PPMO2 = MQ131.getO3(PPM);
Serial.print(PPMO2);
Serial.println(" ppm");
Serial.print("Concentration O3 : ");
PPBO2 = MQ131.getO3(PPB);
Serial.print(PPBO2);
Serial.println(" ppb");
Serial.print("Concentration O3 : ");
MGM3O2 = MQ131.getO3(MG_M3);
Serial.print(MGM3O2);
Serial.println(" mg/m3");
Serial.print("Concentration O3 : ");
UGM3O2 = MQ131.getO3(UG_M3);
Serial.print(UGM3O2);
Serial.println(" ug/m3");
}
//SPI
void MICSVZ89TEMeasure()
{
delay(5000);
MICS_VZ_89TE myMICS;
MICS_status = myMICS.begin();
myMICS.readSensor();
MICS_eqco2 = myMICS.getCO2();
MICS_voc = myMICS.getVOC();
Serial.print("MICS VOC PPB: ");
Serial.println(MICS_voc);
Serial.print("MICS CO2 PPM: ");
Serial.println(MICS_eqco2);
delay(1000);
}
void GyroscopeTurnOn()
{
Wire.begin();
setupMPU();
}
void GyroscopeMeasure() {
recordAccelRegisters();
recordGyroRegisters();
printData();
}
void setupMPU(){
Wire.beginTransmission(0b1101000); //This is the I2C address of the MPU (b1101000/b1101001 for AC0 low/high datasheet sec. 9.2)
Wire.write(0x6B); //Accessing the register 6B - Power Management (Sec. 4.28)
Wire.write(0b00000000); //Setting SLEEP register to 0. (Required; see Note on p. 9)
Wire.endTransmission();
Wire.beginTransmission(0b1101000); //I2C address of the MPU
Wire.write(0x1B); //Accessing the register 1B - Gyroscope Configuration (Sec. 4.4)
Wire.write(0x00000000); //Setting the gyro to full scale +/- 250deg./s
Wire.endTransmission();
Wire.beginTransmission(0b1101000); //I2C address of the MPU
Wire.write(0x1C); //Accessing the register 1C - Acccelerometer Configuration (Sec. 4.5)
Wire.write(0b00000000); //Setting the accel to +/- 2g
Wire.endTransmission();
}
void GyroscopeSleep(){
Wire.beginTransmission(0b1101000); //This is the I2C address of the MPU (b1101000/b1101001 for AC0 low/high datasheet sec. 9.2)
Wire.write(0x6B); //Accessing the register 6B - Power Management (Sec. 4.28)
Wire.write(0b01000000); //Setting SLEEP register to 0. (Required; see Note on p. 9)
Wire.endTransmission();
}
void recordAccelRegisters() {
Wire.beginTransmission(0b1101000); //I2C address of the MPU
Wire.write(0x3B); //Starting register for Accel Readings
Wire.endTransmission();
Wire.requestFrom(0b1101000,6); //Request Accel Registers (3B - 40)
while(Wire.available() < 6);
accelX = Wire.read()<<8|Wire.read(); //Store first two bytes into accelX
accelY = Wire.read()<<8|Wire.read(); //Store middle two bytes into accelY
accelZ = Wire.read()<<8|Wire.read(); //Store last two bytes into accelZ
processAccelData();
}
void processAccelData(){
gForceX = accelX / 16384.0;
gForceY = accelY / 16384.0;
gForceZ = accelZ / 16384.0;
}
void recordGyroRegisters() {
Wire.beginTransmission(0b1101000); //I2C address of the MPU
Wire.write(0x43); //Starting register for Gyro Readings
Wire.endTransmission();
Wire.requestFrom(0b1101000,6); //Request Gyro Registers (43 - 48)
while(Wire.available() < 6);
gyroX = Wire.read()<<8|Wire.read(); //Store first two bytes into accelX
gyroY = Wire.read()<<8|Wire.read(); //Store middle two bytes into accelY
gyroZ = Wire.read()<<8|Wire.read(); //Store last two bytes into accelZ
processGyroData();
}
void processGyroData() {
rotX = gyroX / 131.0;
rotY = gyroY / 131.0;
rotZ = gyroZ / 131.0;
}
void printData() {
Serial.print("Gyro (deg)");
Serial.print(" X=");
Serial.print(rotX);
Serial.print(" Y=");
Serial.print(rotY);
Serial.print(" Z=");
Serial.print(rotZ);
Serial.print(" Accel (g)");
Serial.print(" X=");
Serial.print(gForceX);
Serial.print(" Y=");
Serial.print(gForceY);
Serial.print(" Z=");
Serial.println(gForceZ);
}
void TerrestrialPhase()
{
Serial.println("------------------------------");
Serial.println("TERRESTRIAL PHASE IN PROGRESS");
Serial.println("------------------------------");
Serial.println(" ");
digitalWrite(DcPin, HIGH);
digitalWrite(MICS6814Pin, HIGH);
digitalWrite(MICSVZ89TEPin, HIGH);
digitalWrite(O2Pin, HIGH);
delay(2000);
MICSVZ89TEMeasure();
MICSVZ89TEMeasure();
MICSVZ89TEMeasure();
MICSVZ89TEMeasure();
MICS6814Calibrate();
MICS6814Measure();
SMUARTTurnOn();
delay(10000);
SMUARTMeasure();
delay(10000);
SMUARTMeasure();
delay(1000);
SMUARTMeasure();
delay(1000);
SMUARTMeasure();
delay(1000);
OZONE2CLICKCalibrate();
OZONE2CLICKMeasure();
SDSave();
delay(10000);
RTCBegin();
RTCSleep();
}
void LandingChecker()
{
CurrentTime = millis();
Serial.println(CurrentTime);
if (CurrentTime >= 30000)
{
Serial.println("------------------------------");
Serial.println("AIR PHASE DONE");
Serial.println("------------------------------");
Serial.println(" ");
Serial.println("------------------------------");
Serial.println("STARTING TESTING PHASE");
Serial.println("------------------------------");
Serial.println(" ");
TestingPhase1();
}
else
{
Serial.println("------------------------------");
Serial.println("AIR PHASE IN PROGRESS");
Serial.println("------------------------------");
Serial.println(" ");
}
}
void WaitingPhase()
{
digitalWrite(O2Pin, LOW);
digitalWrite(MICS6814Pin, LOW);
digitalWrite(MICSVZ89TEPin, LOW);
digitalWrite(DcPin, LOW);
digitalWrite(D13_led_pin, LOW);
digitalWrite(M_led_pin, LOW);
GyroscopeSleep();
byte seconds = 0;
byte minutes = 00;
byte hours = 00;
rtc.setTime(hours, minutes, seconds);
rtc.setDate(day, month, year);
rtc.setAlarmTime(00, 00, 10);
rtc.enableAlarm(rtc.MATCH_HHMMSS);
rtc.standbyMode();
TerrestrialPhase();
}
void TestingPhase2()
{
Serial.println("------------------------------");
Serial.println("TESTING PHASE DONE");
Serial.println("------------------------------");
Serial.println(" ");
Serial.println("------------------------------");
Serial.println("STARTING TERRESTRIAL PHASE");
Serial.println("------------------------------");
Serial.println(" ");
TerrestrialPhase();
}
void TestingPhase1()
{
if (((gForceX >= 3.60) || (gForceX <= 0.40)) && ((gForceY >= 2.9) && (gForceY <= 3.20)))
{
Serial.println("------------------------------");
Serial.println("SATELITE POSITION: VERY GOOD");
Serial.println("------------------------------");
Serial.println(" ");
TestingPhase2();
}
else if (((gForceX >= 3.30) || (gForceX <= 0.70)) && ((gForceY >= 2.9) && (gForceY <= 3.30)))
{
Serial.println("------------------------------");
Serial.println("SATELITE POSITION: GOOD");
Serial.println("------------------------------");
Serial.println(" ");
TestingPhase2();
}
else if (((gForceX >= 3) || (gForceX <= 1)) && ((gForceY >= 2.9) && (gForceY <= 4)))
{
Serial.println("------------------------------");
Serial.println("SATELITE POSITION: OK");
Serial.println("------------------------------");
Serial.println(" ");
TestingPhase2();
}
else
{
Serial.println("------------------------------");
Serial.println("SATELITE POSITION: BAD");
Serial.println("------------------------------");
Serial.println(" ");
Serial.println("------------------------------");
Serial.println("TESTING PHASE FAILED");
Serial.println("------------------------------");
Serial.println(" ");
WaitingPhase();
}
}
void SDSave()
{
while(!Serial);
if (!SD.begin(sd_cs_pin))
{
Serial.println("SD card initialization failed!");
return;
}
Serial.println("SD card initialized");
file = SD.open("data.txt", FILE_WRITE); // Open test.txt for write
// Rrite to the file and print info to serial
// print an error to the serial in case it does not succeed
if (file)
{
file.println("--------------------------");
file.println("GyKoVySAT terrestrial data");
file.println("--------------------------");
file.println("OZONE");
file.println(PPMO2);
file.print(" ppm");
file.println(PPBO2);
file.print(" ppb");
file.println(MGM3O2);
file.print(" mg/m³");
file.println("SMOKE PARTICLES STANDART");
file.println(UGM3O2);
file.print(" μg/m³");
file.println(SSmoke1);
file.print(" μg/m³");
file.println(SSmoke2);
file.print(" μg/m³");
file.println(SSmoke3);
file.println("SMOKE PARTICLES ENVIROMENTAL");
file.println(ESmoke1);
file.print(" μg/m³");
file.println(ESmoke2);
file.print(" μg/m³");
file.println(ESmoke3);
file.print(" μg/m³");
file.println("VOC");
file.println(MICS_voc);
file.print(" ppm");
file.println("CO2");
file.println(MICS_eqco2);
file.print(" ppm");
file.println("CO");
file.println(COData);
file.print(" ppm");
file.println("NO2");
file.println(NO2Data);
file.print(" ppm");
file.println("NH3");
file.println(NH3Data);
file.print(" ppm");
file.println("DATA FOR ANALYZATION");
file.println(PPMO2);
file.print(";");
file.print(PPBO2);
file.print(";");
file.print(MGM3O2);
file.print(";");
file.print(UGM3O2);
file.print(";");
file.print(SSmoke1);
file.print(";");
file.print(SSmoke2);
file.print(";");
file.print(SSmoke3);
file.print(";");
file.print(ESmoke1);
file.print(";");
file.print(ESmoke2);
file.print(";");
file.print(ESmoke3);
file.print(";");
file.print(MICS_voc);
file.print(";");
file.print(MICS_eqco2);
file.print(";");
file.print(COData);
file.print(";");
file.print(NO2Data);
file.print(";");
file.print(NH3Data);
file.print(";");
file.print(DataCounter);
file.print(";");
file.close();
DataCounter = DataCounter + 1;
}
else
{
Serial.println("Error opening data.txt for writing");
}
TerrestrialPhase();
}
void setup()
{
// wait for the Arduino serial (on your PC) to connect
// please, open the Arduino serial console (right top corner)
// note that the port may change after uploading the sketch
// COMMENT OUT FOR USAGE WITHOUT A PC!
// while(!Serial);
Serial.println("openCanSat PRO");
Serial.print("Node ");
Serial.print(MYNODEID,DEC);
Serial.println(" ready");
// begin communication with the BME280 on the previously specified address
// print an error to the serial in case the sensor is not found
if (!bme.begin(BME280_ADDRESS_OPEN_CANSAT))
{
isBmeOk = false;
Serial.println("Could not find a valid BME280 sensor, check wiring!");
return;
}
// begin communication with the INA219
ina219.begin();
// check of Gps is connected
Wire.beginTransmission(0x42); // 42 is addres of GPS
int error = Wire.endTransmission();
if (error != 0)
{
isGpsConnected = false;
}
// begin communication with gps
gps.begin();
// Uncomment when you want to see debug prints from GPS library
// gps.debugPrintOn(57600);
if(!radio.initialize(FREQUENCY, MYNODEID, NETWORKID))
{
isRadioOk = false;
Serial.println("RFM69HW initialization failed!");
}
else
{
radio.setFrequency(FREQUENCYSPECIFIC);
radio.setHighPower(true); // Always use this for RFM69HW
}
pinMode(D13_led_pin, OUTPUT);
pinMode(DcPin, OUTPUT);
pinMode(MICS6814Pin, OUTPUT);
pinMode(MICSVZ89TEPin, OUTPUT);
pinMode(O2Pin, OUTPUT);
GyroscopeTurnOn();
}
void loop()
{
cansatdata.messageId = idCounter;
GyroscopeMeasure();
LandingChecker();
Serial.println("MessageId = " + static_cast<String>(cansatdata.messageId));
cansatdata.temperature = 0;
cansatdata.pressure = 0;
cansatdata.altitude = 0;
if(isBmeOk)
{
cansatdata.temperature += bme.readTemperature();
cansatdata.pressure += bme.readPressure() / 100.0F;
cansatdata.altitude += bme.readAltitude(SEALEVELPRESSURE_HPA);
cansatdata.humidity_bme280 = bme.readHumidity();
}
Serial.println("Temperature = " + static_cast<String>(cansatdata.temperature) + " *C");
Serial.println("Pressure = " + static_cast<String>(cansatdata.pressure) + " Pa");
Serial.println("Approx altitude = " + static_cast<String>(cansatdata.altitude) + " m");
Serial.println("Humidity = " + static_cast<String>(cansatdata.humidity_bme280) + " %");
// read values from INA219 into structure
cansatdata.voltage_shunt = ina219.getShuntVoltage_mV();
cansatdata.voltage_bus = ina219.getBusVoltage_V();
cansatdata.current_mA = ina219.getCurrent_mA();
cansatdata.voltage_load = cansatdata.voltage_bus + (cansatdata.voltage_shunt / 1000);
Serial.println("Shunt Voltage: " + static_cast<String>(cansatdata.voltage_shunt) + " mV");
Serial.println("Bus Voltage: " + static_cast<String>(cansatdata.voltage_bus) + " V");
Serial.println("Current: " + static_cast<String>(cansatdata.current_mA) + " mA");
Serial.println("Load Voltage: " + static_cast<String>(cansatdata.voltage_load) + " V");
// Initialize GPS
cansatdata.year = 0;
cansatdata.month = 0 ;
cansatdata.day = 0;
cansatdata.hour = 0;
cansatdata.minute = 0;
cansatdata.sec = 0;
cansatdata.latitude = 0;
cansatdata.longitude = 0;
cansatdata.num_of_satelites = 0;
// save start time in millisec
uint32_t start = millis();
// END LED BLINK
digitalWrite(D13_led_pin, LOW);
pinMode(M_led_pin, INPUT);
// END LED BLINK
if(isGpsConnected)
{
if (gps.scan(250))
{
cansatdata.year = gps.getYear();
cansatdata.month = gps.getMonth();
cansatdata.day = gps.getDay();
cansatdata.hour = gps.getHour();
cansatdata.minute = gps.getMinute();
cansatdata.sec = gps.getSecond();
cansatdata.latitude = gps.getLat();
cansatdata.longitude = gps.getLon();
cansatdata.num_of_satelites = gps.getNumberOfSatellites();
Serial.println(String("Time to find fix: ") + (millis() - start) + String("ms"));
Serial.println(String("Datetime: ") + String(cansatdata.year) + "/"+ String(cansatdata.month) + "/"+ String(cansatdata.day) + " " + String(cansatdata.hour) + ":"+ String(cansatdata.minute) + ":"+ String(cansatdata.sec));
Serial.println(String("Lat: ") + String(cansatdata.latitude, 7));
Serial.println(String("Lon: ") + String(cansatdata.longitude, 7));
Serial.println(String("Num of sats: ") + String(cansatdata.num_of_satelites));
Serial.println();
}
else
{
Serial.println("Gps have no satelit to fix.");
}
}
// RFM69HW
cansatdata.rssi = 0;
if(isRadioOk)
{
cansatdata.rssi = radio.RSSI;
Serial.println("Signal = " + static_cast<String>(radio.RSSI));
radio.send(TONODEID, (const void*)&cansatdata, sizeof(cansatdata));
}
Serial.println();
// START LED hart beat
pinMode(M_led_pin, OUTPUT);
digitalWrite(D13_led_pin, HIGH);
digitalWrite(M_led_pin, HIGH);
// START LED hart beat
if(!isGpsConnected)
{
delay(200);
}
idCounter ++;
}
大多数 SPI 接口可以置于 'loopback' 模式,这使得代码可以轻松检查 activity 以验证 transmitted/received 数据
关于:
if (error != 0)
{
isGpsConnected = false;
}
// begin communication with gps
gps.begin();
如果没有连接 GPS,则不应尝试与 GPS 通信。建议:
if (error != 0)
{
isGpsConnected = false;
return;
}
else
{
// begin communication with gps
gps.begin();
}