Skip to content

Commit

Permalink
Support for V440 module hardware
Browse files Browse the repository at this point in the history
  • Loading branch information
stuartpittaway committed Feb 24, 2021
1 parent b4309a0 commit 593a81c
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 67 deletions.
2 changes: 1 addition & 1 deletion ATTINYCellModule/include/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Attribution-NonCommercial-ShareAlike 2.0 UK: England & Wales (CC BY-NC-SA 2.0 UK
#error You need to specify the DIYBMSMODULEVERSION define
#endif

#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION > 430
#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION > 440
#error Incorrect value for DIYBMSMODULEVERSION
#endif

Expand Down
72 changes: 56 additions & 16 deletions ATTINYCellModule/include/diybms_attiny841.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ class DiyBMSATTiny841
//Switch OFF Bit 1 – OCIE1A: Timer/Counter, Output Compare A Match Interrupt Enable
TIMSK1 &= (~_BV(OCIE1A));
}

static void StartTimer1()
{
//Normal port operation, OC1A/OC1B disconnected
Expand All @@ -50,7 +49,7 @@ class DiyBMSATTiny841

// Prescaler 8Mhz/64 = 125000 counts per second, call ISR 1000 times per second
// Prescaler 2Mhz/64 = 31250 counts per second, call ISR 1000 times per second - roughly, as rounding error of 31.25
OCR1A = (F_CPU/64)/1000;
OCR1A = (F_CPU / 64) / 1000;

ResumePWM();
}
Expand All @@ -61,14 +60,39 @@ class DiyBMSATTiny841
DumpLoadOff();
}

static void SetPrescaler()
{
//Boot up will be in 1Mhz CKDIV8 mode, swap to /4 to change speed to 2Mhz
byte oldSREG = SREG;
cli();
/*atomic code, as its time sensitive*/;
//CCP – Configuration Change Protection Register
CCP = 0xD8;
//CLKPR – Clock Prescale Register
CLKPR = _BV(CLKPS1);
SREG = oldSREG;
}

static void DumpLoadOn()
{
#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 440
//Pre 4.4 board
PORTA |= _BV(PORTA3);
#else
//4.4 board
PORTB |= _BV(PORTB2);
#endif
}

static void DumpLoadOff()
{
#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 440
//Pre 4.4 board
PORTA &= (~_BV(PORTA3));
#else
//4.4 board
PORTB &= (~_BV(PORTB2));
#endif
}

static void ReferenceVoltageOn()
Expand All @@ -83,17 +107,17 @@ class DiyBMSATTiny841
PORTA &= (~_BV(PORTA7));
}

static void GreenLedOn()
static void NotificationLedOn()
{
PORTA |= _BV(PORTA6);
}

static void GreenLedOff()
static void NotificationLedOff()
{
PORTA &= (~_BV(PORTA6));
}

#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 430
#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 440
static void SparePinOn()
{
PORTB |= _BV(PORTB1);
Expand All @@ -105,7 +129,7 @@ class DiyBMSATTiny841
}
#endif

#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 430
#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 440
static void BlueLedOn()
{
PORTA |= _BV(PORTA5);
Expand Down Expand Up @@ -179,36 +203,52 @@ class DiyBMSATTiny841

static void SelectCellVoltageChannel()
{
#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 440
//Pre 4.4 board
//PB2 = ADC8 PIN 5 ARDUINO PIN 2/A8 = VOLTAGE reading
//ADMUXA – ADC Multiplexer Selection Register A
//ADC8 (single end) MUX[5:0] 00 1000
ADMUXA = (0 << MUX5) | (0 << MUX4) | (1 << MUX3) | (0 << MUX2) | (0 << MUX1) | (0 << MUX0);
//ADMUXA = (0 << MUX5) | (0 << MUX4) | (1 << MUX3) | (0 << MUX2) | (0 << MUX1) | (0 << MUX0);
ADMUXA = B00001000;

#else
//4.4 board

//PA3 = ADC3 PIN 10 = VOLTAGE READING
//See Page 144 in the datasheet for information
//ADMUXA = (0 << MUX5) | (0 << MUX4) | (0 << MUX3) | (0 << MUX2) | (1 << MUX1) | (1 << MUX0);
ADMUXA = B00000011;

#endif
}

static void SelectInternalTemperatureChannel()
{
//PA4
//ADMUXA – ADC Multiplexer Selection Register A
//ADC4 (single end) MUX[5:0] 00 0100
ADMUXA = (0 << MUX5) | (0 << MUX4) | (0 << MUX3) | (1 << MUX2) | (0 << MUX1) | (0 << MUX0);
//ADMUXA = (0 << MUX5) | (0 << MUX4) | (0 << MUX3) | (1 << MUX2) | (0 << MUX1) | (0 << MUX0);
ADMUXA = B00000100;
}

static void SelectExternalTemperatureChannel()
{
//External sensor
//ADMUXA – ADC Multiplexer Selection Register A
//External sensor
//ADMUXA – ADC Multiplexer Selection Register A

#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 430
#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 440
//ADC11 (single end) MUX[5:0] 00 1011
ADMUXA = (0 << MUX5) | (0 << MUX4) | (1 << MUX3) | (0 << MUX2) | (1 << MUX1) | (1 << MUX0);
//ADMUXA = (0 << MUX5) | (0 << MUX4) | (1 << MUX3) | (0 << MUX2) | (1 << MUX1) | (1 << MUX0);
ADMUXA = B00001011;
#else
//V4.3 boards ADC5 (single end) MUX[5:0] 00 0101
ADMUXA = (0 << MUX5) | (0 << MUX4) | (0 << MUX3) | (1 << MUX2) | (0 << MUX1) | (1 << MUX0);
//V4.4 boards ADC5 (single end) MUX[5:0] 00 0101
//ADMUXA = (0 << MUX5) | (0 << MUX4) | (0 << MUX3) | (1 << MUX2) | (0 << MUX1) | (1 << MUX0);
ADMUXA = B00000101;
#endif
}

static void double_tap_green_led();
#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 430
static void double_tap_Notification_led();
#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 440
static void double_tap_blue_led();
#endif
};
Expand Down
28 changes: 26 additions & 2 deletions ATTINYCellModule/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
; [Blue LED removed, resetable fuse fitted]
;** DO NOT FLASH V430 TO AN OLDER BOARD - THE ATTINY WILL BECOME UNUSABLE **
[platformio]
default_envs = V400, V410, V420, V420_SWAPR19R20, V421, V421_LTO
default_envs = V400, V410, V420, V420_SWAPR19R20, V421, V421_LTO, V440
description=DIYBMS Cell monitoring module code

[env]
Expand Down Expand Up @@ -61,7 +61,7 @@ upload_flags =
-Pusb
-Ulfuse:w:0b01100010:m
-Uhfuse:w:0b11010110:m
-Uefuse:w:0b11110100:m
-Uefuse:w:0b11110100:m

[env:V400]
; 8 balance resistors marked 2R2
Expand All @@ -88,3 +88,27 @@ build_flags=-DDIYBMSMODULEVERSION=421 -DMV_PER_ADC=2.00 -DINT_BCOEFFICIENT=4050
;Round PCB with bolt hole. 10 balance resistors marked 6.2OHM
;Uses resistor divider circuit of 18.2K/13K ohms = 1.24V output for 3.00V input
build_flags=-DDIYBMSMODULEVERSION=421 -DMV_PER_ADC=1.00 -DINT_BCOEFFICIENT=3950 -DEXT_BCOEFFICIENT=3950 -DLOAD_RESISTANCE=2.48 -DBAUD=2400

[env:V440]
;DIYBMS V4.40 - DO NOT USE THIS SETTING WITH OLDER BOARDS THEY
; WILL BE RENDERED USELESS (CLOCK FUSE CHANGES)
;Almost completely different pin mapping compared to previous modules
;Single LED and external crystal (8Mhz), has breakaway thermistor sub pcb board
;Has fuse and TVS diode on inputs and uses AZ432ANTR-E1 voltage reference
;PA0/PA6/PA4/PA7 are same purpose as previous boards
;PB2 = DUMP LOAD ENABLE, PA3 = VOLTAGE ADC, PA5 = EXT THERMISTOR ADC
;BLUE LED DOES NOT EXIST ON V440 (Well it does, but the green has been replaced with blue!)
build_flags=-DDIYBMSMODULEVERSION=440 -DMV_PER_ADC=2.00 -DINT_BCOEFFICIENT=3950 -DEXT_BCOEFFICIENT=3950 -DLOAD_RESISTANCE=3.30 -DBAUD=2400
; Fuses E:F4, H:D6, L:62
; lfuse = 0110 0010 = CKDIV8 (enabled) & Calibrated Internal 8MHz Oscillator
; hfuse = 1101 0110 = EESAVE & 1.8V BOD detection level
; efuse = 1111 0100 = Enables SPM instruction
board_fuses.lfuse = 0b01101100
board_fuses.hfuse = 0b11010110
board_fuses.efuse = 0b11110100
;-B16 option needed for my USBASP programmer to slow it down!
upload_flags =
-Pusb
-Ulfuse:w:0b01101100:m
-Uhfuse:w:0b11010110:m
-Uefuse:w:0b11110100:m
75 changes: 54 additions & 21 deletions ATTINYCellModule/src/diybms_attiny841.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,30 +38,42 @@ FOR MODULE VERSION 400,410,420,421....
PA3 = DUMP LOAD ENABLE / PIN 10 / ARDUINO PIN 7/A3 / TOCC2
PA4 = ADC4 PIN 9 ARDUINO PIN 6/A4 = ON BOARD TEMP sensor
PA5 = SERIAL PORT 1 TXD1 - NOT USED (BLUE LED ON <V430 BOARDS AND EXT TEMP SENSOR ON >=430)
PA6 = GREEN_LED / PIN 7 / ARDUINO PIN 4/A6
PA6 = Notification LED / PIN 7 / ARDUINO PIN 4/A6
PA7 = ADC7 = PIN 6 = ARDUINO PIN 3/A7 = 2.048V REFERENCE ENABLE
PB2 = ADC8 PIN 5 ARDUINO PIN 2/A8 = VOLTAGE reading
PB0 = ADC11 PIN 2 ARDUINO PIN 0/A11 = REMOTE TEMP sensor = XTAL
PB1 = ADC10 PIN 3 ARDUINO PIN 1/A10 = SPARE INPUT/OUTPUT = XTAL
ATTiny841 data sheet
http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-8495-8-bit-AVR-Microcontrollers-ATtiny441-ATtiny841_Datasheet.pdf
V440 pin mappings
PA0 = EXT REFERENCE
PA6 = Notification LED
PA4 = INT THERMISTOR ADC
PA7 = ENABLE
PB2 = DUMP LOAD ENABLE
PA3 = VOLTAGE ADC
PA5 = EXT THERMISTOR ADC
BLUE LED DOES NOT EXIST ON V440 (Well it does, but the green has been replaced with blue!)
*/

#include "diybms_attiny841.h"

void DiyBMSATTiny841::double_tap_green_led()
void DiyBMSATTiny841::double_tap_Notification_led()
{
GreenLedOn();
NotificationLedOn();
delay(50);
GreenLedOff();
NotificationLedOff();
delay(50);
GreenLedOn();
NotificationLedOn();
delay(50);
GreenLedOff();
NotificationLedOff();
}

#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 430
#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 440
void DiyBMSATTiny841::double_tap_blue_led()
{
BlueLedOn();
Expand All @@ -81,17 +93,35 @@ void DiyBMSATTiny841::ConfigurePorts()
//PUEB – Port B Pull-Up Enable Control Register (All disabled)
PUEB = 0;

//DDRA – Port A Data Direction Register
//When DDAn is set, the pin PAn is configured as an output. When DDAn is cleared, the pin is configured as an input
#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 430
DDRA |= _BV(DDA3) | _BV(DDA6) | _BV(DDA7) | _BV(DDA5);
#else
//4.3 boards dont have blue led, so don't configure DA5
DDRA |= _BV(DDA3) | _BV(DDA6) | _BV(DDA7);
#endif
//DDRA – Port A Data Direction Register
//When DDAn is set, the pin PAn is configured as an output. When DDAn is cleared, the pin is configured as an input
#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 440
//PA3 = dump load enable
//PA6 = Notification LED (green)
//PA7 = enable
//PA5 = BLUE
DDRA = _BV(DDA3) | _BV(DDA6) | _BV(DDA7) | _BV(DDA5);
//DDRB – Port B Data Direction Register
//Spare pin is output
DDRB |= _BV(DDB1);
DDRB = _BV(DDB1);

//Digital Input Disable Register 0
//PA4 (ADC4), PB2 (ADC8) and PB0 (ADC11) analog inputs, so disable digital pins to save power
DIDR0 = _BV(ADC4D);
DIDR1 = _BV(ADC8D) |_BV(ADC11D);

#else
//4.4 boards don't have blue led
//PB2 = DUMP LOAD ENABLE
//PA6 = Notification LED (BLUE)
//PA7 = ENABLE
DDRA = _BV(DDA6) | _BV(DDA7);
DDRB = _BV(DDB2);

//Digital Input Disable Register 0
//PA3 (ADC3), PA4 (ADC4) and PA5 (ADC5) are analog inputs, so disable digital pins to save power
DIDR0 = _BV(ADC3D) | _BV(ADC4D) |_BV(ADC5D);
#endif

//Set the extra high sink capability of pin PA7 is enabled.
PHDE |= _BV(PHDEA1);
Expand All @@ -100,10 +130,11 @@ void DiyBMSATTiny841::ConfigurePorts()
DumpLoadOff();
ReferenceVoltageOff();

#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 430
#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 440
BlueLedOff();
#endif
GreenLedOff();

NotificationLedOff();
}

void DiyBMSATTiny841::SetWatchdog8sec()
Expand Down Expand Up @@ -140,18 +171,20 @@ void DiyBMSATTiny841::BeginADCReading()
//ADCSRA – ADC Control and Status Register A
//Consider ADC sleep conversion mode?

/*
#if !(F_CPU == 8000000)
//prescaler of 64 = 8MHz/64 = 125KHz.
ADCSRA |= _BV(ADPS2) | _BV(ADPS1); // | _BV(ADPS0);
#endif
#if !(F_CPU == 2000000)
*/

//prescaler of 16 = 2MHz/16 = 125000.
ADCSRA |= _BV(ADPS2);
#endif

//#endif

//adc_enable();
//Bit 4 – ADIF: ADC Interrupt Flag
//Bit 7 – ADEN: ADC Enable
ADCSRA |= _BV(ADEN) | _BV(ADIF); // enable ADC, turn off any pending interrupt
Expand Down Expand Up @@ -189,7 +222,7 @@ void DiyBMSATTiny841::Sleep()
// disable ADC
ADCSRA = 0;

#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 430
#if defined(DIYBMSMODULEVERSION) && DIYBMSMODULEVERSION < 440
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
#else
//Using an external crystal so keep it awake - consumes more power (about 0.97mA vs 0.78mA) but module wakes quicker (6 clock cycles)
Expand Down
Loading

0 comments on commit 593a81c

Please sign in to comment.