mirror of https://github.com/rusefi/8Ch-EGT.git
First platformio release for v2.0
This commit is contained in:
parent
195bf64b55
commit
861fa61489
|
@ -0,0 +1,13 @@
|
|||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
.history
|
||||
.vscode
|
||||
Arduino core/egt.s-platofrmio/.history
|
||||
Arduino core/egt.s-platofrmio/.pio
|
||||
Arduino core/egt.s-platofrmio/.vscode/.browse.c_cpp.db*
|
||||
Arduino core/egt.s-platofrmio/.vscode/c_cpp_properties.json
|
||||
Arduino core/egt.s-platofrmio/.vscode/launch.json
|
||||
Arduino core/egt.s-platofrmio/.vscode/ipch
|
|
@ -0,0 +1,6 @@
|
|||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
.history
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the usual convention is to give header files names that end with `.h'.
|
||||
It is most portable to use only letters, digits, dashes, and underscores in
|
||||
header file names, and at most one dot.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into executable file.
|
||||
|
||||
The source code of each library should be placed in a an own separate directory
|
||||
("lib/your_library_name/[here are source files]").
|
||||
|
||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
and a contents of `src/main.c`:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
|
@ -0,0 +1,14 @@
|
|||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:genericSTM32F103C8]
|
||||
platform = ststm32
|
||||
board = genericSTM32F103C8
|
||||
framework = arduino
|
|
@ -0,0 +1,244 @@
|
|||
/***************************************************************************************************/
|
||||
/*
|
||||
This is an Arduino library for 14-bit MAX31855 K-Thermocouple to Digital Converter
|
||||
with 12-bit Cold Junction Compensation conneted to hardware 5Mhz SPI with maximum sampling
|
||||
rate ~9..10Hz.
|
||||
|
||||
- MAX31855 maximum power supply voltage is 3.6v
|
||||
- K-type thermocouples have an absolute accuracy of around ±2°C..±6°C.
|
||||
- Measurement tempereture range -200°C..+700°C ±2°C or -270°C..+1372°C ±6°C
|
||||
with 0.25°C resolution/increment.
|
||||
- Cold junction compensation range -40°C..+125° ±3°C with 0.062°C resolution/increment.
|
||||
Optimal performance of cold junction compensation happends when the thermocouple cold junction
|
||||
& the MAX31855 are at the same temperature. Avoid placing heat-generating devices or components
|
||||
near the converter because this may produce an errors.
|
||||
- It is strongly recommended to add a 10nF/0.01mF ceramic surface-mount capacitor, placed across
|
||||
the T+ and T- pins, to filter noise on the thermocouple lines.
|
||||
|
||||
written by : enjoyneering79
|
||||
sourse code: https://github.com/enjoyneering/MAX31855
|
||||
|
||||
This sensor uses SPI bus to communicate, specials pins are required to interface
|
||||
Board: MOSI MISO SCLK SS, don't use for CS Level
|
||||
Uno, Mini, Pro, ATmega168, ATmega328..... 11 12 13 10 5v
|
||||
Mega, Mega2560, ATmega1280, ATmega2560... 51 50 52 53 5v
|
||||
Due, SAM3X8E............................. ICSP4 ICSP1 ICSP3 x 3.3v
|
||||
Leonardo, ProMicro, ATmega32U4........... 16 14 15 x 5v
|
||||
Blue Pill, STM32F103xxxx boards.......... PA17 PA6 PA5 PA4 3v
|
||||
NodeMCU 1.0, WeMos D1 Mini............... GPIO13/D7 GPIO12/D6 GPIO14/D5 GPIO15/D8* 3v/5v
|
||||
ESP32.................................... GPIO23/D23 GPIO19/D19 GPIO18/D18 x 3v
|
||||
|
||||
*if GPIO2/D4 or GPIO0/D3 is used for for CS, apply an external
|
||||
25kOhm pullup-down resistor otherwise reset & reset button
|
||||
may not work
|
||||
|
||||
Frameworks & Libraries:
|
||||
ATtiny Core - https://github.com/SpenceKonde/ATTinyCore
|
||||
ESP32 Core - https://github.com/espressif/arduino-esp32
|
||||
ESP8266 Core - https://github.com/esp8266/Arduino
|
||||
STM32 Core - https://github.com/rogerclarkmelbourne/Arduino_STM32
|
||||
|
||||
GNU GPL license, all text above must be included in any redistribution,
|
||||
see link for details - https://www.gnu.org/licenses/licenses.html
|
||||
*/
|
||||
/***************************************************************************************************/
|
||||
|
||||
#include "MAX31855.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
MAX31855()
|
||||
|
||||
Constructor for hardware read only SPI
|
||||
|
||||
NOTE:
|
||||
- cs is chip select, set CS low to enable the serial interface
|
||||
*/
|
||||
/**************************************************************************/
|
||||
MAX31855::MAX31855(uint8_t cs)
|
||||
{
|
||||
_cs = cs; //cs chip select
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
begin()
|
||||
|
||||
Initializes & configures hardware SPI
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void MAX31855::begin(void)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); //disables SPI interface for MAX31855, but it will initiate measurement/conversion
|
||||
|
||||
SPI.begin(); //setting hardware SCK, MOSI, SS to output, pull SCK, MOSI low & SS high
|
||||
|
||||
delay(MAX31855_CONVERSION_POWER_UP_TIME);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
detectThermocouple()
|
||||
|
||||
Checks if thermocouple is open, shorted to GND, shorted to VCC
|
||||
|
||||
Return:
|
||||
- 0 OK
|
||||
- 1 short to VCC
|
||||
- 2 short to GND
|
||||
- 3 not connected
|
||||
|
||||
NOTE:
|
||||
- bit D16 is normally low & goes high if thermocouple is open, shorted to GND or VCC
|
||||
- bit D2 is normally low & goes high to indicate a hermocouple short to VCC
|
||||
- bit D1 is normally low & goes high to indicate a thermocouple short to GND
|
||||
- bit D0 is normally low & goes high to indicate a thermocouple open circuit
|
||||
*/
|
||||
/**************************************************************************/
|
||||
uint8_t MAX31855::detectThermocouple(int32_t rawValue)
|
||||
{
|
||||
if (rawValue == MAX31855_FORCE_READ_DATA) rawValue = readRawData();
|
||||
|
||||
if (bitRead(rawValue, 16) == 1)
|
||||
{
|
||||
if (bitRead(rawValue, 2) == 1) return MAX31855_THERMOCOUPLE_SHORT_TO_VCC;
|
||||
else if (bitRead(rawValue, 1) == 1) return MAX31855_THERMOCOUPLE_SHORT_TO_GND;
|
||||
else if (bitRead(rawValue, 0) == 1) return MAX31855_THERMOCOUPLE_NOT_CONNECTED;
|
||||
else return MAX31855_THERMOCOUPLE_UNKNOWN;
|
||||
}
|
||||
return MAX31855_THERMOCOUPLE_OK;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
getChipID()
|
||||
|
||||
Checks chip ID
|
||||
|
||||
NOTE:
|
||||
- bit D17, D3 always return zero & can be used as device ID
|
||||
*/
|
||||
/**************************************************************************/
|
||||
uint16_t MAX31855::getChipID(int32_t rawValue)
|
||||
{
|
||||
if (rawValue == MAX31855_FORCE_READ_DATA) rawValue = readRawData();
|
||||
|
||||
if (bitRead(rawValue, 17) == 0 && bitRead(rawValue, 3) == 0) return MAX31855_ID;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
getTemperature()
|
||||
|
||||
Reads Temperature, C
|
||||
|
||||
NOTE:
|
||||
- range -200°C..+700°C ±2°C or -270°C..+1372°C ±6°C with 0.25°C
|
||||
resolution/increment
|
||||
- thermocouple temperature data is 14-bit long
|
||||
- bit D31 is the thermocouple temperature sign bit "+" is high & "-" is low,
|
||||
if T+ and T- are unconnected it goes low
|
||||
- bits D30..D18 contain the converted temperature in the order of MSB to LSB,
|
||||
if T+ and T- are unconnected they go high
|
||||
- it is strongly recommended to add a 10nF/0.01mF ceramic surface-mount
|
||||
capacitor, placed across the T+ and T- pins, to filter noise on the
|
||||
thermocouple lines
|
||||
*/
|
||||
/**************************************************************************/
|
||||
float MAX31855::getTemperature(int32_t rawValue)
|
||||
{
|
||||
if (rawValue == MAX31855_FORCE_READ_DATA) rawValue = readRawData();
|
||||
|
||||
if (detectThermocouple(rawValue) != MAX31855_THERMOCOUPLE_OK || getChipID(rawValue) != MAX31855_ID) return MAX31855_ERROR;
|
||||
|
||||
rawValue = rawValue >> 18; //clear D17..D0 bits
|
||||
|
||||
return (float)rawValue * MAX31855_THERMOCOUPLE_RESOLUTION;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
getColdJunctionTemperature()
|
||||
|
||||
Reads Temperature, C
|
||||
|
||||
NOTE:
|
||||
- range -40°C..+125° ±3°C with 0.062°C resolution/increment
|
||||
- chip internal temperature data is 12-bit long
|
||||
- bit D15 is cold-junction temperature sign bit "+" is high & "-" is low
|
||||
- bits D14..D4 contain cold-junction temperature in the order of MSB to LSB
|
||||
*/
|
||||
/**************************************************************************/
|
||||
float MAX31855::getColdJunctionTemperature(int32_t rawValue)
|
||||
{
|
||||
if (rawValue == MAX31855_FORCE_READ_DATA) rawValue = readRawData();
|
||||
|
||||
if (getChipID(rawValue) != MAX31855_ID) return MAX31855_ERROR;
|
||||
|
||||
rawValue = rawValue & 0x0000FFFF; //clear D31..D16 bits
|
||||
rawValue = rawValue >> 4; //clear D3...D0 bits
|
||||
|
||||
return (float)rawValue * MAX31855_COLD_JUNCTION_RESOLUTION;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
readRawData()
|
||||
|
||||
Reads raw data from MAX31855 via hardware SPI
|
||||
|
||||
NOTE:
|
||||
- read of the cold-junction compensated thermocouple temperature requires
|
||||
14 clock cycles
|
||||
- read of the cold-junction compensated thermocouple temperature & reference
|
||||
junction temperatures requires 32 clock cycles
|
||||
- forcing CS low immediately stops any conversion process, force CS high
|
||||
to initiate a new measurement process
|
||||
- set CS low to enable the serial interface & force to output the first bit on the SO pin,
|
||||
apply 14/32 clock signals at SCK to read the results at SO on the falling edge of the SCK
|
||||
- bit D31 is the thermocouple temperature sign bit "+" is high & "-" is low,
|
||||
if T+ & T- pins are unconnected it goes low
|
||||
- bits D30..D18 contain the converted temperature in the order of MSB to LSB,
|
||||
if T+ & T- pins are unconnected they go high
|
||||
- bit D17 is low to provide a device ID for the MAX31855
|
||||
- bit D16 is normally low & goes high if thermocouple is open, shorted to GND or VCC
|
||||
- bit D15 is cold-junction temperature sign bit "+" is high & "-" is low
|
||||
- bits D14..D4 contain cold-junction temperature in the order of MSB to LSB
|
||||
- bit D3 is is low to provide a device ID for the MAX31855
|
||||
- bit D2 is normally low & goes high to indicate a hermocouple short to VCC
|
||||
- bit D1 is normally low & goes high to indicate a thermocouple short to GND
|
||||
- bit D0 is normally low & goes high to indicate a thermocouple open circuit
|
||||
|
||||
- max SPI master clock speed is equal with board speed
|
||||
(16000000UL for 5V 16MHz/ProMini), but MAX31855 max speed is only 5MHz
|
||||
- SPI_MODE0 -> capture data on clock's falling edge
|
||||
*/
|
||||
/**************************************************************************/
|
||||
int32_t MAX31855::readRawData(void)
|
||||
{
|
||||
int32_t rawData = 0;
|
||||
|
||||
digitalWrite(_cs, LOW); //stop measurement/conversion
|
||||
delayMicroseconds(1); //4MHz is 0.25usec, do we need it???
|
||||
digitalWrite(_cs, HIGH); //start measurement/conversion
|
||||
delay(MAX31855_CONVERSION_TIME);
|
||||
|
||||
SPI.beginTransaction(SPISettings(5000000UL, MSBFIRST, SPI_MODE0)); //speed ~5MHz, read MSB first, SPI mode 0, see note
|
||||
|
||||
digitalWrite(_cs, LOW); //set CS low to enable SPI interface for MAX31855
|
||||
|
||||
for (uint8_t i = 0; i < 2; i++) //read 32-bits via hardware SPI, in order MSB->LSB (D31..D0 bit)
|
||||
{
|
||||
rawData = (rawData << 16) | SPI.transfer16(0x0000); //chip has read only SPI & MOSI not connected, so it doesn't metter what to send
|
||||
}
|
||||
|
||||
digitalWrite(_cs, HIGH); //disables SPI interface for MAX31855, but it will initiate measurement/conversion
|
||||
|
||||
SPI.endTransaction(); //de-asserting hw chip select & free hw SPI for other slaves
|
||||
|
||||
return rawData;
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/***************************************************************************************************/
|
||||
/*
|
||||
This is an Arduino library for 14-bit MAX31855 K-Thermocouple to Digital Converter
|
||||
with 12-bit Cold Junction Compensation conneted to hardware 5Mhz SPI with maximum sampling
|
||||
rate ~9..10Hz.
|
||||
|
||||
- MAX31855 maximum power supply voltage is 3.6v
|
||||
- K-type thermocouples have an absolute accuracy of around ±2°C..±6°C.
|
||||
- Measurement tempereture range -200°C..+700°C ±2°C or -270°C..+1372°C ±6°C
|
||||
with 0.25°C resolution/increment.
|
||||
- Cold junction compensation range -40°C..+125° ±3°C with 0.062°C resolution/increment.
|
||||
Optimal performance of cold junction compensation happends when the thermocouple cold junction
|
||||
& the MAX31855 are at the same temperature. Avoid placing heat-generating devices or components
|
||||
near the converter because this may produce an errors.
|
||||
- It is strongly recommended to add a 10nF/0.01mF ceramic surface-mount capacitor, placed across
|
||||
the T+ and T- pins, to filter noise on the thermocouple lines.
|
||||
|
||||
written by : enjoyneering79
|
||||
sourse code: https://github.com/enjoyneering/MAX31855
|
||||
|
||||
This sensor uses SPI bus to communicate, specials pins are required to interface
|
||||
Board: MOSI MISO SCLK SS, don't use for CS Level
|
||||
Uno, Mini, Pro, ATmega168, ATmega328..... 11 12 13 10 5v
|
||||
Mega, Mega2560, ATmega1280, ATmega2560... 51 50 52 53 5v
|
||||
Due, SAM3X8E............................. ICSP4 ICSP1 ICSP3 x 3.3v
|
||||
Leonardo, ProMicro, ATmega32U4........... 16 14 15 x 5v
|
||||
Blue Pill, STM32F103xxxx boards.......... PA17 PA6 PA5 PA4 3v
|
||||
NodeMCU 1.0, WeMos D1 Mini............... GPIO13/D7 GPIO12/D6 GPIO14/D5 GPIO15/D8* 3v/5v
|
||||
ESP32.................................... GPIO23/D23 GPIO19/D19 GPIO18/D18 x 3v
|
||||
|
||||
*if GPIO2/D4 or GPIO0/D3 is used for for CS, apply an external
|
||||
25kOhm pullup-down resistor otherwise reset & reset button
|
||||
may not work
|
||||
|
||||
Frameworks & Libraries:
|
||||
ATtiny Core - https://github.com/SpenceKonde/ATTinyCore
|
||||
ESP32 Core - https://github.com/espressif/arduino-esp32
|
||||
ESP8266 Core - https://github.com/esp8266/Arduino
|
||||
STM32 Core - https://github.com/rogerclarkmelbourne/Arduino_STM32
|
||||
|
||||
GNU GPL license, all text above must be included in any redistribution,
|
||||
see link for details - https://www.gnu.org/licenses/licenses.html
|
||||
*/
|
||||
/***************************************************************************************************/
|
||||
|
||||
#ifndef MAX31855_h
|
||||
#define MAX31855_h
|
||||
|
||||
#if defined(ARDUINO) && ((ARDUINO) >= 100) //arduino core v1.0 or later
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <WProgram.h>
|
||||
#endif
|
||||
|
||||
#if defined(__AVR__)
|
||||
#include <avr/pgmspace.h> //use for PROGMEM Arduino AVR
|
||||
#elif defined(ESP8266)
|
||||
#include <pgmspace.h> //use for PROGMEM Arduino ESP8266
|
||||
#elif defined(_VARIANT_ARDUINO_STM32_)
|
||||
#include <avr/pgmspace.h> //use for PROGMEM Arduino STM32
|
||||
#endif
|
||||
|
||||
#ifndef MAX31855_SOFT_SPI //enable upload spi.h
|
||||
#include <SPI.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define MAX31855_CONVERSION_POWER_UP_TIME 200 //in milliseconds
|
||||
#define MAX31855_CONVERSION_TIME 10 //in milliseconds, this was 100, but we are reading 8 chips so this should still give enough time
|
||||
#define MAX31855_THERMOCOUPLE_RESOLUTION 0.25 //in °C per dac step
|
||||
#define MAX31855_COLD_JUNCTION_RESOLUTION 0.0625 //in °C per dac step
|
||||
|
||||
|
||||
#define MAX31855_ID 31855
|
||||
#define MAX31855_FORCE_READ_DATA 7 //force to read the data, 7 is unique because d2d1d0 can't be all high at the same time
|
||||
#define MAX31855_ERROR 2000 //returned value if any error happends
|
||||
|
||||
#define MAX31855_THERMOCOUPLE_OK 0
|
||||
#define MAX31855_THERMOCOUPLE_SHORT_TO_VCC 1
|
||||
#define MAX31855_THERMOCOUPLE_SHORT_TO_GND 2
|
||||
#define MAX31855_THERMOCOUPLE_NOT_CONNECTED 3
|
||||
#define MAX31855_THERMOCOUPLE_UNKNOWN 4
|
||||
|
||||
|
||||
class MAX31855
|
||||
{
|
||||
public:
|
||||
MAX31855(uint8_t cs);
|
||||
|
||||
void begin(void);
|
||||
uint8_t detectThermocouple(int32_t rawValue = MAX31855_FORCE_READ_DATA);
|
||||
uint16_t getChipID(int32_t rawValue = MAX31855_FORCE_READ_DATA);
|
||||
float getTemperature(int32_t rawValue = MAX31855_FORCE_READ_DATA);
|
||||
float getColdJunctionTemperature(int32_t rawValue = MAX31855_FORCE_READ_DATA);
|
||||
int32_t readRawData(void);
|
||||
|
||||
private:
|
||||
|
||||
protected:
|
||||
uint8_t _cs;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,286 @@
|
|||
#include <Arduino.h>
|
||||
#include "MAX31855.h"
|
||||
|
||||
#define DEBUG 1
|
||||
|
||||
#ifndef DEBUG
|
||||
#define DEBUG 0
|
||||
#endif
|
||||
|
||||
#if DEBUG > 0
|
||||
#define LOG_D Serial.printf
|
||||
#else
|
||||
#define LOG_D
|
||||
#endif
|
||||
|
||||
#define EGT_SPEED 100
|
||||
|
||||
|
||||
HardwareSerial Serial3(USART3); //for some reason this isn't defined in arduino_core_stm32
|
||||
|
||||
#define Sensor1_4_CAN_ADDRESS 0x20A //the data from sensers 1-4 will be sent using this address
|
||||
#define Sensor5_8_CAN_ADDRESS 0x20B //the data from sensers 5-8 will be sent using this address
|
||||
|
||||
enum BitRate { CAN_50KBPS, CAN_100KBPS, CAN_125KBPS, CAN_250KBPS, CAN_500KBPS, CAN_1000KBPS };
|
||||
|
||||
typedef struct {
|
||||
uint16_t id;
|
||||
uint8_t data[8];
|
||||
uint8_t len;
|
||||
} CAN_msg_t;
|
||||
|
||||
typedef const struct {
|
||||
uint8_t TS2;
|
||||
uint8_t TS1;
|
||||
uint8_t BRP;
|
||||
} CAN_bit_timing_config_t;
|
||||
|
||||
CAN_bit_timing_config_t can_configs[6] = {{2, 13, 45}, {2, 15, 20}, {2, 13, 18}, {2, 13, 9}, {2, 15, 4}, {2, 15, 2}};
|
||||
|
||||
CAN_msg_t CAN_msg_14; // data from egt 1-4 that will be sent to CAN bus
|
||||
CAN_msg_t CAN_msg_58; // data from egt 5-8 that will be sent to CAN bus
|
||||
uint16_t canAddress;
|
||||
uint8_t canin_channel;
|
||||
|
||||
extern CAN_bit_timing_config_t can_configs[6];
|
||||
|
||||
uint8_t cs[8] = { PA0, PA1, PA2, PA3, PB0, PB1, PB13, PB12 }; //chip select pins for the MAX31855 chips
|
||||
int32_t rawData[8] = { 0 }; //raw data from all 8 MAX31855 chips
|
||||
|
||||
int16_t egt[8] = { 0 }; //calculated egt values from all 8 MAX31855 chips
|
||||
int16_t coldJunction[8] = { 0 }; //calculated cold junction temperatures from all 8 MAX31855 chips, not needed for any other than debugging
|
||||
|
||||
uint8_t max31855_OK_bits; // this is used to check if all MAX31855 chips are working or even installed and code skips the ones that don't work.
|
||||
|
||||
MAX31855 MAX31855_chips[8] = {
|
||||
MAX31855(cs[0]),
|
||||
MAX31855(cs[1]),
|
||||
MAX31855(cs[2]),
|
||||
MAX31855(cs[3]),
|
||||
MAX31855(cs[4]),
|
||||
MAX31855(cs[5]),
|
||||
MAX31855(cs[6]),
|
||||
MAX31855(cs[7])
|
||||
};
|
||||
|
||||
|
||||
enum IdCan {
|
||||
ID_CAN0,
|
||||
ID_CAN1,
|
||||
ID_CAN2,
|
||||
ID_CAN3,
|
||||
ID_CAN4,
|
||||
ID_CAN_SIZE
|
||||
};
|
||||
|
||||
enum IdPins {
|
||||
ID_PIN0 = PB3,
|
||||
ID_PIN1 = PB4,
|
||||
ID_PIN2 = PB5,
|
||||
ID_PIN3 = PB6,
|
||||
ID_PIN4 = PB7,
|
||||
CAN_SPEED_PIN = PB8
|
||||
};
|
||||
|
||||
struct IdAddrCan {
|
||||
uint8_t pin;
|
||||
uint8_t shift;
|
||||
};
|
||||
|
||||
IdAddrCan pins[ID_CAN_SIZE] = {
|
||||
{ ID_PIN0, 4 },
|
||||
{ ID_PIN1, 5 },
|
||||
{ ID_PIN2, 6 },
|
||||
{ ID_PIN3, 7 },
|
||||
{ ID_PIN4, 10 },
|
||||
};
|
||||
|
||||
void canInit(enum BitRate bitrate) {
|
||||
RCC->APB1ENR |= 0x2000000UL; // Enable CAN clock
|
||||
RCC->APB2ENR |= 0x1UL; // Enable AFIO clock
|
||||
AFIO->MAPR &= 0xFFFF9FFF; // reset CAN remap
|
||||
AFIO->MAPR |= 0x00000000; // set CAN remap, use PA11, PA12
|
||||
|
||||
RCC->APB2ENR |= 0x4UL; // Enable GPIOA clock (bit2 to 1)
|
||||
GPIOA->CRH &= 0xFFF00FFF;
|
||||
GPIOA->CRH |= 0xB8000UL; // Configure PA11 and PA12
|
||||
GPIOA->ODR |= 0x1000UL;
|
||||
|
||||
CAN1->MCR = 0x51UL; // Set CAN to initialization mode
|
||||
|
||||
// Set bit rates
|
||||
CAN1->BTR &= ~(((0x03) << 24) | ((0x07) << 20) | ((0x0F) << 16) | (0x1FF));
|
||||
CAN1->BTR |= (((can_configs[bitrate].TS2-1) & 0x07) << 20) | (((can_configs[bitrate].TS1-1) & 0x0F) << 16) | ((can_configs[bitrate].BRP-1) & 0x1FF);
|
||||
|
||||
// Configure Filters to default values
|
||||
CAN1->FMR |= 0x1UL; // Set to filter initialization mode
|
||||
CAN1->FMR &= 0xFFFFC0FF; // Clear CAN2 start bank
|
||||
CAN1->FMR |= 0x1C << 8; // Assign all filters to CAN1
|
||||
CAN1->FA1R &= ~(0x1UL); // Deactivate filter 0
|
||||
CAN1->FS1R |= 0x1UL; // Set first filter to single 32 bit configuration
|
||||
|
||||
CAN1->sFilterRegister[0].FR1 = 0x0UL; // Set filter registers to 0
|
||||
CAN1->sFilterRegister[0].FR2 = 0x0UL; // Set filter registers to 0
|
||||
CAN1->FM1R &= ~(0x1UL); // Set filter to mask mode
|
||||
|
||||
CAN1->FFA1R &= ~(0x1UL); // Apply filter to FIFO 0
|
||||
CAN1->FA1R |= 0x1UL; // Activate filter 0
|
||||
|
||||
CAN1->FMR &= ~(0x1UL); // Deactivate initialization mode
|
||||
CAN1->MCR &= ~(0x1UL); // Set CAN to normal mode
|
||||
while(CAN1->MSR & 0x1UL);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
pinMode(CAN_SPEED_PIN, INPUT_PULLUP);
|
||||
uint16_t canMask = 0;
|
||||
for(uint8_t i = 0; i < ID_CAN_SIZE; ++i) {
|
||||
pinMode(pins[i].pin, INPUT_PULLUP);
|
||||
delay(1);
|
||||
canMask |= (!digitalRead(pins[i].pin)) << pins[i].shift;
|
||||
}
|
||||
max31855_OK_bits = 0;
|
||||
Serial.begin(115200); //debug
|
||||
Serial3.begin(115200); //data to speeduino
|
||||
canInit(digitalRead(CAN_SPEED_PIN) ? CAN_500KBPS : CAN_1000KBPS); //init can at 500KBPS speed
|
||||
CAN_msg_14.len = 8; //8 bytes in can message
|
||||
CAN_msg_58.len = 8;
|
||||
CAN_msg_14.id = Sensor1_4_CAN_ADDRESS | canMask;
|
||||
CAN_msg_58.id = Sensor5_8_CAN_ADDRESS | canMask;
|
||||
|
||||
// begin communication to MAX31855 chips
|
||||
for(uint32_t i = 0; i < 8; ++i) {
|
||||
MAX31855_chips[i].begin();
|
||||
}
|
||||
|
||||
// check that all MAX31855 chips work or are even installed
|
||||
for(uint32_t i = 0; i < 8; ++i) {
|
||||
if (MAX31855_chips[i].readRawData() != 0) { //we will just get 0 if there is no chip at all.
|
||||
if (MAX31855_chips[i].getChipID() != MAX31855_ID) //if there is something there, check that it responds like MAX31855 (maybe useless step)
|
||||
{
|
||||
LOG_D("MAX31855 %d Error\r\n", i+1);
|
||||
}
|
||||
else{
|
||||
bitSet(max31855_OK_bits, i); //set corresponding bit to 1
|
||||
}
|
||||
}
|
||||
else{
|
||||
LOG_D("Can't find MAX31855 %d\r\n", i+1); //nothing in this CS line
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sendDataToSpeeduino() {
|
||||
// Consider Serial.printf("G1%d", canin_channel);
|
||||
Serial3.write("G"); // reply "G" cmd
|
||||
Serial3.write(1); //send 1 to confirm cmd received and valid
|
||||
Serial3.write(canin_channel); //confirms the destination channel
|
||||
if((canAddress & Sensor1_4_CAN_ADDRESS) == Sensor1_4_CAN_ADDRESS) {
|
||||
for(uint32_t i = 0; i < 8; ++i) {
|
||||
Serial3.write(CAN_msg_14.data[i]);
|
||||
}
|
||||
}
|
||||
if((canAddress & Sensor5_8_CAN_ADDRESS) == Sensor1_4_CAN_ADDRESS) {
|
||||
for(uint32_t i = 0; i < 8; ++i) {
|
||||
Serial3.write(CAN_msg_58.data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkDataRequest() {
|
||||
if(Serial3.read() == 'R') {
|
||||
uint8_t tmp0;
|
||||
uint8_t tmp1;
|
||||
if(Serial3.available() >= 3) {
|
||||
canin_channel = Serial3.read();
|
||||
tmp0 = Serial3.read(); //read in lsb of source can address
|
||||
tmp1 = Serial3.read(); //read in msb of source can address
|
||||
canAddress = tmp1<<8 | tmp0 ;
|
||||
if((canAddress & Sensor1_4_CAN_ADDRESS) == Sensor1_4_CAN_ADDRESS
|
||||
|| (canAddress & Sensor5_8_CAN_ADDRESS) == Sensor1_4_CAN_ADDRESS) { //check if the speeduino request includes adresses for EGTs
|
||||
sendDataToSpeeduino(); //request ok, send the data to speeduino
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void canSend(CAN_msg_t* CAN_tx_msg) {
|
||||
volatile uint32_t count = 0;
|
||||
|
||||
CAN1->sTxMailBox[0].TIR = (CAN_tx_msg->id) << 21;
|
||||
|
||||
CAN1->sTxMailBox[0].TDTR &= ~(0xF);
|
||||
CAN1->sTxMailBox[0].TDTR |= CAN_tx_msg->len & 0xFUL;
|
||||
|
||||
CAN1->sTxMailBox[0].TDLR = (((uint32_t) CAN_tx_msg->data[3] << 24) |
|
||||
((uint32_t) CAN_tx_msg->data[2] << 16) |
|
||||
((uint32_t) CAN_tx_msg->data[1] << 8) |
|
||||
((uint32_t) CAN_tx_msg->data[0] ));
|
||||
CAN1->sTxMailBox[0].TDHR = (((uint32_t) CAN_tx_msg->data[7] << 24) |
|
||||
((uint32_t) CAN_tx_msg->data[6] << 16) |
|
||||
((uint32_t) CAN_tx_msg->data[5] << 8) |
|
||||
((uint32_t) CAN_tx_msg->data[4] ));
|
||||
CAN1->sTxMailBox[0].TIR |= 0x1UL;
|
||||
while(CAN1->sTxMailBox[0].TIR & 0x1UL && count++ < 1000000);
|
||||
|
||||
// if (!(CAN1->sTxMailBox[0].TIR & 0x1UL)) return;
|
||||
|
||||
//Sends error log to screen
|
||||
if(CAN1->sTxMailBox[0].TIR & 0x1UL) {
|
||||
LOG_D("ESR %5lu MSR %5lu TSR %5lu\r\n", CAN1->ESR, CAN1->MSR, CAN1->TSR);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
static uint32_t egtQueryStamp = 0;
|
||||
uint32_t currentTime = millis();
|
||||
if((currentTime - egtQueryStamp) > EGT_SPEED) {
|
||||
egtQueryStamp = currentTime;
|
||||
for(uint32_t i = 0; i < 8; ++i) {
|
||||
if(bitRead(max31855_OK_bits, i) == 1) {
|
||||
rawData[i] = MAX31855_chips[i].readRawData();
|
||||
LOG_D("EGT%d: ", i+1);
|
||||
switch(MAX31855_chips[i].detectThermocouple(rawData[i])) {
|
||||
case MAX31855_THERMOCOUPLE_OK:
|
||||
//egt[i] = (MAX31855_chips[i].getTemperature(rawData[i]));
|
||||
egt[i] = (rawData[i] >> 18)/4;
|
||||
LOG_D("Temp: %6d\r\n", egt[i]);
|
||||
break;
|
||||
case MAX31855_THERMOCOUPLE_SHORT_TO_VCC:
|
||||
LOG_D("SHORT TO VCC\r\n");
|
||||
egt[i] = 2000;
|
||||
break;
|
||||
case MAX31855_THERMOCOUPLE_SHORT_TO_GND:
|
||||
LOG_D("SHORT TO GND\r\n");
|
||||
egt[i] = 3000;
|
||||
break;
|
||||
case MAX31855_THERMOCOUPLE_NOT_CONNECTED:
|
||||
LOG_D("NOT CONNECTED\r\n");
|
||||
egt[i] = 4000;
|
||||
break;
|
||||
default:
|
||||
LOG_D("MAX31855 ERROR\r\n");
|
||||
egt[i] = 5000;
|
||||
break;
|
||||
}
|
||||
//coldJunction[i] = (MAX31855_chips[i].getColdJunctionTemperature(rawData[i]));
|
||||
coldJunction[i] = ((rawData[i] & 0xFFFF) >> 4)/16;
|
||||
if (i < 4) {
|
||||
CAN_msg_14.data[2*i] = lowByte ((uint16_t)(egt[i]));
|
||||
CAN_msg_14.data[2*i+1] = highByte((uint16_t)(egt[i]));
|
||||
} else{
|
||||
CAN_msg_58.data[2*i-8] = lowByte ((uint16_t)(egt[i]));
|
||||
CAN_msg_58.data[2*i-7] = highByte((uint16_t)(egt[i]));
|
||||
}
|
||||
LOG_D("Cold Junction %5d \r\n Temp: %6d", i+1, coldJunction[i]);
|
||||
}
|
||||
}
|
||||
canSend(&CAN_msg_14);
|
||||
canSend(&CAN_msg_58);
|
||||
}
|
||||
|
||||
while(Serial3.available () > 0) { //is there data on serial3, presumably from speeduino
|
||||
checkDataRequest(); //there is data, but is request from speeduino and is it for EGTs
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
This directory is intended for PlatformIO Test Runner and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PlatformIO Unit Testing:
|
||||
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
|
Loading…
Reference in New Issue