Skip to content

Commit

Permalink
Adaption for ATmega644.
Browse files Browse the repository at this point in the history
  • Loading branch information
Armin committed Jun 19, 2024
1 parent 5f7ae47 commit 502fa46
Show file tree
Hide file tree
Showing 16 changed files with 490 additions and 129 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/TestCompile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ jobs:
- arduino:avr:uno|LOCAL_DEBUG
- arduino:avr:uno|DISPLAY_ALWAYS_ON
- arduino:avr:uno|USE_NO_LCD
- MightyCore:avr:644

include:
- arduino-boards-fqbn: arduino:avr:uno|STANDALONE_TEST
Expand All @@ -49,6 +50,11 @@ jobs:
build-properties:
All: -DUSE_NO_LCD

- arduino-boards-fqbn: MightyCore:avr:644
platform-url: https://mcudude.github.io/MightyCore/package_MCUdude_MightyCore_index.json
build-properties:
All: -DANDRES_644_BOARD

steps:
- name: Checkout
uses: actions/checkout@master
Expand All @@ -57,4 +63,6 @@ jobs:
uses: ArminJo/arduino-test-compile@master
with:
# required-libraries: EasyButtonAtInt01,SoftI2CMaster
arduino-board-fqbn: ${{ matrix.arduino-boards-fqbn }}
platform-url: ${{ matrix.platform-url }}
build-properties: ${{ toJson(matrix.build-properties) }}
234 changes: 234 additions & 0 deletions JK-BMSToPylontechCAN/ADCUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
/*
* ADCUtils.h
*
* Copyright (C) 2016-2022 Armin Joachimsmeyer
* Email: [email protected]
*
* This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils.
*
* ArduinoUtils 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/gpl.html>.
*
*/

#ifndef _ADC_UTILS_H
#define _ADC_UTILS_H

#include <Arduino.h>

#if defined(__AVR__) && defined(ADCSRA) && defined(ADATE) && (!defined(__AVR_ATmega4809__))
#define ADC_UTILS_ARE_AVAILABLE

// PRESCALE4 => 13 * 4 = 52 microseconds per ADC conversion at 1 MHz Clock => 19,2 kHz
#define ADC_PRESCALE2 1 // 26 microseconds per ADC conversion at 1 MHz
#define ADC_PRESCALE4 2 // 52 microseconds per ADC conversion at 1 MHz
// PRESCALE8 => 13 * 8 = 104 microseconds per ADC sample at 1 MHz Clock => 9,6 kHz
#define ADC_PRESCALE8 3 // 104 microseconds per ADC conversion at 1 MHz
#define ADC_PRESCALE16 4 // 13/208 microseconds per ADC conversion at 16/1 MHz - degradations in linearity at 16 MHz
#define ADC_PRESCALE32 5 // 26/416 microseconds per ADC conversion at 16/1 MHz - very good linearity at 16 MHz
#define ADC_PRESCALE64 6 // 52 microseconds per ADC conversion at 16 MHz
#define ADC_PRESCALE128 7 // 104 microseconds per ADC conversion at 16 MHz --- Arduino default

// definitions for 0.1 ms conversion time
#if (F_CPU == 1000000)
#define ADC_PRESCALE ADC_PRESCALE8
#elif (F_CPU == 8000000)
#define ADC_PRESCALE ADC_PRESCALE64
#elif (F_CPU == 16000000)
#define ADC_PRESCALE ADC_PRESCALE128
#endif

/*
* Reference shift values are complicated for ATtinyX5 since we have the extra register bit REFS2
* in ATTinyCore, this bit is handled programmatical and therefore the defines are different.
* To keep my library small, I use the changed defines.
* After including this file you can not call the ATTinyCore readAnalog functions reliable, if you specify references other than default!
*/
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
// defines are for ADCUtils.cpp, they can be used WITHOUT bit reordering
#undef DEFAULT
#undef EXTERNAL
#undef INTERNAL1V1
#undef INTERNAL
#undef INTERNAL2V56
#undef INTERNAL2V56_EXTCAP

#define DEFAULT 0
#define EXTERNAL 4
#define INTERNAL1V1 8
#define INTERNAL INTERNAL1V1
#define INTERNAL2V56 9
#define INTERNAL2V56_EXTCAP 13

#define SHIFT_VALUE_FOR_REFERENCE REFS2
#define MASK_FOR_ADC_REFERENCE (_BV(REFS0) | _BV(REFS1) | _BV(REFS2))
#define MASK_FOR_ADC_CHANNELS (_BV(MUX0) | _BV(MUX1) | _BV(MUX2) | _BV(MUX3))
#else // AVR_ATtiny85

#define SHIFT_VALUE_FOR_REFERENCE REFS0
#define MASK_FOR_ADC_REFERENCE (_BV(REFS0) | _BV(REFS1))
#define MASK_FOR_ADC_CHANNELS (_BV(MUX0) | _BV(MUX1) | _BV(MUX2) | _BV(MUX3))
#endif

// Temperature channel definitions - 1 LSB / 1 degree Celsius
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#define ADC_TEMPERATURE_CHANNEL_MUX 15
#define ADC_1_1_VOLT_CHANNEL_MUX 12
#define ADC_GND_CHANNEL_MUX 13
#define ADC_CHANNEL_MUX_MASK 0x0F

#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#define ADC_ISCR_CHANNEL_MUX 3
#define ADC_TEMPERATURE_CHANNEL_MUX 11
#define ADC_1_1_VOLT_CHANNEL_MUX 12
#define ADC_GND_CHANNEL_MUX 14
#define ADC_VCC_4TH_CHANNEL_MUX 13
#define ADC_CHANNEL_MUX_MASK 0x1F

#elif defined(__AVR_ATmega328P__)
#define ADC_TEMPERATURE_CHANNEL_MUX 8
#define ADC_1_1_VOLT_CHANNEL_MUX 14
#define ADC_GND_CHANNEL_MUX 15
#define ADC_CHANNEL_MUX_MASK 0x0F

#elif defined(__AVR_ATmega644P__)
#define ADC_TEMPERATURE_CHANNEL_MUX // not existent
#define ADC_1_1_VOLT_CHANNEL_MUX 0x1E
#define ADC_GND_CHANNEL_MUX 0x1F
#define ADC_CHANNEL_MUX_MASK 0x0F

#elif defined(__AVR_ATmega32U4__)
#define ADC_TEMPERATURE_CHANNEL_MUX 0x27
#define ADC_1_1_VOLT_CHANNEL_MUX 0x1E
#define ADC_GND_CHANNEL_MUX 0x1F
#define ADC_CHANNEL_MUX_MASK 0x3F

#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
#define ADC_1_1_VOLT_CHANNEL_MUX 0x1E
#define ADC_GND_CHANNEL_MUX 0x1F
#define ADC_CHANNEL_MUX_MASK 0x1F

#define INTERNAL INTERNAL1V1

#else
#error "No temperature channel definitions specified for this AVR CPU"
#endif

/*
* Thresholds for OVER and UNDER voltage and detection of kind of power supply (USB or Li-ion)
*
* Default values are suitable for Li-ion batteries.
* We normally have voltage drop at the connectors, so the battery voltage is assumed slightly higher, than the Arduino VCC.
* But keep in mind that the ultrasonic distance module HC-SR04 may not work reliable below 3.7 volt.
*/
#if !defined(LI_ION_VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT)
#define LI_ION_VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT 3400 // Do not stress your battery and we require some power for standby
#endif
#if !defined(LI_ION_VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT)
#define LI_ION_VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT 3000 // Many Li-ions are specified down to 3.0 volt
#endif

#if !defined(VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT)
#define VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT LI_ION_VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT
#endif
#if !defined(VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT)
#define VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT LI_ION_VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT
#endif
#if !defined(VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT)
#define VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT 5250 // + 5 % operation voltage
#endif
#if !defined(VCC_EMERGENCY_OVERVOLTAGE_THRESHOLD_MILLIVOLT)
#define VCC_EMERGENCY_OVERVOLTAGE_THRESHOLD_MILLIVOLT 5500 // +10 %. Max recommended operation voltage
#endif
#if !defined(VCC_CHECK_PERIOD_MILLIS)
#define VCC_CHECK_PERIOD_MILLIS 10000L // 10 seconds period of VCC checks
#endif
#if !defined(VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP)
#define VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP 6 // Shutdown after 6 times (60 seconds) VCC below VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT or 1 time below VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT
#endif

#if !defined(VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT)
#define VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT 4300 // Assume USB powered above this voltage
#endif

#if !defined(VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT)
#define VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT 4950 // Assume USB powered below this voltage, because of the loss in USB cable. If we have > 4950, we assume to be powered by VIN.
// In contrast to e.g. powered by VIN, which results in almost perfect 5 volt supply
#endif

extern long sLastVCCCheckMillis;
extern uint8_t sVCCTooLowCounter;

uint16_t readADCChannel(uint8_t aADCChannelNumber);
uint16_t readADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference);
uint16_t waitAndReadADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference);
uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t aADCChannelNumber, uint8_t aReference);
uint16_t readADCChannelWithOversample(uint8_t aADCChannelNumber, uint8_t aOversampleExponent);
void setADCChannelAndReferenceForNextConversion(uint8_t aADCChannelNumber, uint8_t aReference);
uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent);
uint32_t readADCChannelMultiSamples(uint8_t aPrescale, uint16_t aNumberOfSamples);
uint16_t readADCChannelMultiSamplesWithReference(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples);
uint32_t readADCChannelMultiSamplesWithReferenceAndPrescaler(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aPrescale,
uint16_t aNumberOfSamples);
uint16_t readADCChannelWithReferenceMax(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aNumberOfSamples);
uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aMicrosecondsToAquire);
uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aDelay,
uint8_t aAllowedDifference, uint8_t aMaxRetries);

uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aADCChannelNumber, uint8_t aReference);

/*
* readVCC*() functions store the result in sVCCVoltageMillivolt or sVCCVoltage
*/
float getVCCVoltageSimple(void);
void readVCCVoltageSimple(void);
void readVCCVoltageMillivoltSimple(void);
void readVCCVoltage(void);
uint16_t getVCCVoltageMillivolt(void);
void readVCCVoltageMillivolt(void);
uint16_t getVCCVoltageReadingFor1_1VoltReference(void);
uint16_t printVCCVoltageMillivolt(Print *aSerial);
void readAndPrintVCCVoltageMillivolt(Print *aSerial);

uint16_t getVoltageMillivolt(uint16_t aVCCVoltageMillivolt, uint8_t aADCChannelForVoltageMeasurement);
uint16_t getVoltageMillivolt(uint8_t aADCChannelForVoltageMeasurement);
uint16_t getVoltageMillivoltWith_1_1VoltReference(uint8_t aADCChannelForVoltageMeasurement);
float getCPUTemperatureSimple(void);
float getCPUTemperature(void);
float getTemperature(void) __attribute__ ((deprecated ("Renamed to getCPUTemperature()"))); // deprecated

bool isVCCUSBPowered();
bool isVCCUSBPowered(Print *aSerial);
bool isVCCUndervoltageMultipleTimes();
void resetCounterForVCCUndervoltageMultipleTimes();
bool isVCCUndervoltage();
bool isVCCEmergencyUndervoltage();
bool isVCCOvervoltage();
bool isVCCOvervoltageSimple(); // Version using readVCCVoltageMillivoltSimple()
bool isVCCTooHighSimple(); // Version not using readVCCVoltageMillivoltSimple()

#endif // defined(__AVR__) ...

/*
* Variables and functions defined as dummies to allow for seamless compiling on non AVR platforms
*/
extern float sVCCVoltage;
extern uint16_t sVCCVoltageMillivolt;

uint16_t readADCChannelWithReferenceOversample(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent);

uint16_t getVCCVoltageMillivoltSimple(void);
float getVCCVoltage(void);
float getCPUTemperature(void);

#endif // _ADC_UTILS_H
15 changes: 8 additions & 7 deletions JK-BMSToPylontechCAN/AVRUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Stack, Ram and Heap utilities.
* Sleep utilities.
*
* Copyright (C) 2016-2023 Armin Joachimsmeyer
* Copyright (C) 2016-2024 Armin Joachimsmeyer
* Email: [email protected]
*
* This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils.
Expand Down Expand Up @@ -212,21 +212,22 @@ void printStackUnusedAndUsedBytesIfChanged(Print *aSerial) {
* It ends with the heap and the stack.
*
* Sample output if stack runs into data:
* Size of Data + BSS, Heap start, Stack end=2041
* Stack used 20 of 7
* Currently available Heap=0
* Size of Data + BSS / Heap start=0x773 | 1907
* Currently available Heap=7
* Stack used 100 of 141
*/
void printRAMInfo(Print *aSerial) {
uint16_t tHeapStart = (uint16_t) getHeapStart();
aSerial->print(F("Size of Data + BSS, Heap start, Stack end=0x"));
aSerial->print(F("Size of Data + BSS / Heap start=0x"));
aSerial->print(tHeapStart - RAMSTART, HEX);
aSerial->print(F(" | "));
aSerial->println(tHeapStart - RAMSTART);

printStackUsedBytes(aSerial);

aSerial->print(F("Currently available Heap="));
aSerial->println(getCurrentAvailableHeap());

printStackUsedBytes(aSerial);

}

void printCurrentFreeHeap(Print *aSerial) {
Expand Down
12 changes: 11 additions & 1 deletion JK-BMSToPylontechCAN/EasyButtonAtInt01.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* EasyButtonAtInt01.hpp
* EasyButtonAtInt01.h
*
* Arduino library for handling push buttons connected between ground and INT0 and / or INT1 pin.
* INT0 and INT1 are connected to Pin 2 / 3 on most Arduinos (ATmega328), to PB6 / PA3 on ATtiny167 and on ATtinyX5 we have only INT0 at PB2.
Expand Down Expand Up @@ -170,6 +170,16 @@
#define INT1_OUT_PORT (PORTB)
# endif // defined(USE_BUTTON_1)

#elif defined(USE_INT2_FOR_BUTTON_0) // Hack for ATmega 644
# if defined(USE_BUTTON_1)
#error If USE_INT2_FOR_BUTTON_0 is defined, only USE_BUTTON_0 is allowed, USE_BUTTON_1 must be disabled!
# endif
// dirty hack, but INT0 and INT1 are occupied by second USART
#define INT0_PIN 2 // PB2 / INT2
#define INT0_DDR_PORT (DDRB)
#define INT0_IN_PORT (PINB)
#define INT0_OUT_PORT (PORTB)

#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
// from here we use only ATtinyCore / PAx / PBx numbers, since on Digispark board and core library there is used a strange enumeration of pins
#define INT0_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards and labeled with 3 (D3)
Expand Down
22 changes: 20 additions & 2 deletions JK-BMSToPylontechCAN/EasyButtonAtInt01.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,12 @@ void EasyButton::init(bool aIsButtonAtINT0) {
sPointerToButton0ForISR = this;
# if defined(USE_ATTACH_INTERRUPT)
attachInterrupt(digitalPinToInterrupt(INT0_PIN), &handleINT0Interrupt, CHANGE);

# elif defined(USE_INT2_FOR_BUTTON_0)
EICRA |= _BV(ISC20); // interrupt on any logical change
EIFR |= _BV(INTF2);// clear interrupt bit
EIMSK |= _BV(INT2);// enable interrupt on next change

# else
EICRA |= _BV(ISC00); // interrupt on any logical change
EIFR |= _BV(INTF0);// clear interrupt bit
Expand Down Expand Up @@ -722,8 +728,8 @@ void __attribute__ ((weak)) handleINT1Interrupt() {
// ISR for PIN PD2
// Cannot make the vector itself weak, since the vector table is already filled by weak vectors resulting in ignoring my weak one:-(
//ISR(INT0_vect, __attribute__ ((weak))) {
# if defined(USE_BUTTON_0)
ISR(INT0_vect) {
# if defined(USE_INT2_FOR_BUTTON_0)
ISR(INT2_vect) {
# if defined(MEASURE_EASY_BUTTON_INTERRUPT_TIMING)
digitalWriteFast(INTERRUPT_TIMING_OUTPUT_PIN, HIGH);
# endif
Expand All @@ -732,6 +738,18 @@ ISR(INT0_vect) {
digitalWriteFast(INTERRUPT_TIMING_OUTPUT_PIN, LOW);
# endif
}
# else
# if defined(USE_BUTTON_0)
ISR(INT0_vect) {
# if defined(MEASURE_EASY_BUTTON_INTERRUPT_TIMING)
digitalWriteFast(INTERRUPT_TIMING_OUTPUT_PIN, HIGH);
# endif
handleINT0Interrupt();
# if defined(MEASURE_EASY_BUTTON_INTERRUPT_TIMING)
digitalWriteFast(INTERRUPT_TIMING_OUTPUT_PIN, LOW);
# endif
}
# endif
# endif

# if defined(USE_BUTTON_1)
Expand Down
Loading

0 comments on commit 502fa46

Please sign in to comment.