Mysensor-ing a thermostatic valve
-
I have ordered 2 HR25 valves.
these valves are an update of the HR20 with a atmega329 instead of 169.My idea is the following:
The easy part (widely documented).- connect an ISP connecto to the PCB.
- connect an NRF24L01 to the PCB
The harder part:
- use the atmega329 with arduino boatloader and framework: Probably doable, but not natively supported. Might need some tweaking in the bootloader sources.
- flash the atmega with a simple mysensor sketch as proof of concept.
Then, the development step by step:
- First a simple mysensor actuator wich will directly operate the valve motor.
- Following step: get the internal temperature sensor working
- Then: integrate PID control loop. -> The setting point would be given over the air by MySensor controller
- Then use the internal LCD and buttons for local control. The LCD library of openHR (AVR C) is probably a good starting point.
-
That's right. I don't need the bootloader itself.
edit:
This a memo for myself :
http://www.instructables.com/id/Arduino-on-all-sorts-of-Atmels/?ALLSTEPS
Atmega3290 is supported and is pretty close of atmega 329. -
Hey guys,
Some news,I have received 2 HR25 TRV.
I have tried to connect an ISP header to one of them.
The good news is: MISO/MOSI/SCK/GND/VCC./and RESET are easily available on the upper part of the PCB. (SPI pins are used for the 3 buttons and power and reset are already available on the Jtag header.
The bad news is that it is quite easy to damge the pcb while welding. I have had a problem with two coppers traces that went away of the PCB... probably because of overheat. Theses traces were so thin, that until now i hav not been able to weld a jumper to repair them.
However , i will try again tonight.Regarding the software, i think i have been able to set-up the arduino IDE to compile for an atmega329p target. I have to test it to validate the process.
-
Hi there,
I have been able to make some progress.
The cutted traces have been repaired with some thin wire. However, this board is definitely damaged. I think this one will remain my "guinea pig".after repairing the traces, i have tested the isp connection:
sorg@samsung-ubuntu:~$ avrdude -c usbasp -p m329p avrdude: warning: cannot set sck period. please check for usbasp firmware update. avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.00s avrdude: Device signature = 0x1e950b avrdude: safemode: Fuses OK (E:FD, H:91, L:62) avrdude done. Thank you.:heart_eyes:
No it's time to set-up the arduino IDE for compiling...
in my Arduino/hardware/boards.txt, i have hadded the following lines:
##############################################################hr25.name=HoneyWell HR25 Thermostat/ programming with USBasp hr25.upload.using=USBasp hr25.upload.protocol=usb hr25.upload.maximum_size=30720 hr25.upload.speed=38400 hr25.build.mcu=atmega329p hr25.build.f_cpu=16000000L hr25.build.core=arduino hr25.build.variant=hr25Then, i have created a new folder named "hr25" in Arduino/hardware/variants , and in this folder i create a file named pins_arduino.h and put the following inside:
/* pins_arduino.h - Pin definition functions for Arduino Part of Arduino - http://www.arduino.cc/ Copyright (c) 2007 David A. Mellis This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *************************************** Definition for ATmega329p as in the HR25 thermostat */ #ifndef Pins_Arduino_h #define Pins_Arduino_h #include <avr/pgmspace.h> #define NUM_DIGITAL_PINS 53 #define NUM_ANALOG_INPUTS 8 #define analogInputToDigitalPin(p) ((p < 8) ? (p) + 40 : -1) #define digitalPinHasPWM(p) ((p) == 12 || (p) == 14 || (p) == 15 || (p) == 13) static const uint8_t SS = 8; //PB0 static const uint8_t MOSI = 10; //PB2 static const uint8_t MISO = 11; //PB3 static const uint8_t SCK = 9; //PB1 static const uint8_t SDA = 37; //PE5 static const uint8_t SCL = 36; //PE4 // #define LED_BUILTIN 13 static const uint8_t A0 = 40; //PF0 static const uint8_t A1 = 41; //PF1 static const uint8_t A2 = 42; //PF2 static const uint8_t A3 = 43; //PF3 static const uint8_t A4 = 44; //PF4 static const uint8_t A5 = 45; //PF5 static const uint8_t A6 = 46; //PF6 static const uint8_t A7 = 47; //PF7 // Not sure of that... atmega168 use PCICR whereas the atmegaxx9 seems to use a EIMSK register... Will it work ? #define digitalPinToPCICR(p) ( (((p) >= 32) && ((p) <= 39)) || (((p) >= 8) && ((p) <= 15)) ? (&EIMSK) : \ ((uint8_t *)0) ) ) #define digitalPinToPCICRbit(p) ( (((p) >= 32) && ((p) <= 39)) ? 4 : \ ( (((p) >= 8) && ((p) <= 15)) ? 5 : \ ((uint8_t *)0) ) ) #define digitalPinToPCMSK(p) ( (((p) >= 32) && ((p) <= 39)) ? (&PCMSK0) : \ ( (((p) >= 8) && ((p) <= 15)) ? (&PCMSK1) : \ ((uint8_t *)0) ) ) #define digitalPinToPCMSKbit(p) ( (((p) >= 32) && ((p) <= 39)) ? ((p) - 32) : \ ( (((p) >= 8) && ((p) <= 15)) ? ((p) - 8) : \ ((uint8_t *)0) ) ) #define digitalPinToInterrupt(p) ((p) == 24 ? 0 : NOT_AN_INTERRUPT) #ifdef ARDUINO_MAIN // these arrays map port names (e.g. port B) to the // appropriate addresses for various functions (e.g. reading // and writing) const uint16_t PROGMEM port_to_mode_PGM[] = { NOT_A_PORT, (uint16_t) &DDRA, (uint16_t) &DDRB, (uint16_t) &DDRC, (uint16_t) &DDRD, (uint16_t) &DDRE, (uint16_t) &DDRF, (uint16_t) &DDRG, }; const uint16_t PROGMEM port_to_output_PGM[] = { NOT_A_PORT, (uint16_t) &PORTA, (uint16_t) &PORTB, (uint16_t) &PORTC, (uint16_t) &PORTD, (uint16_t) &PORTE, (uint16_t) &PORTF, (uint16_t) &PORTG, }; const uint16_t PROGMEM port_to_input_PGM[] = { NOT_A_PORT, (uint16_t) &PINA, (uint16_t) &PINB, (uint16_t) &PINC, (uint16_t) &PIND, (uint16_t) &PINE, (uint16_t) &PINF, (uint16_t) &PING, }; const uint8_t PROGMEM digital_pin_to_port_PGM[] = { PA, // 0 // LCD_Com0 PA, // LCD_Com1 PA, // LCD_Com2 PA, PA, // LCD_Seg0 PA, // LCD_Seg1 PA, // LCD_Seg2 PA, // LCD_Seg3 PB, // 8 - NSS - PCINT8 // Contact - Thermostat installed on the valve PB, // 9 - SCK - PCINT9 // KEY °C PB, // 10 - MOSI - PCINT10 // KEY Prog PB, // 11 - MISO - PCINT11 // KEY Auto/Manu PB, // 12 - PWM - PCINT12 // H-Bridge 1 PB, // 13 - PWM - PCINT13 // Incremental coder A PB, // 14 - PWM - PCINT14 // Incremental coder B PB, // 15 - PWM - PCINT15 // H-Bridge 2 PC, // 16 // LCD_Seg12 PC, // 17 // LCD_Seg11 PC, // 18 // LCD_Seg10 PC, // 19 // LCD_Seg9 PC, // 20 // LCD_Seg8 PC, // 21 // LCD_Seg7 PC, // 22 // LCD_Seg6 PC, // 23 // LCD_Seg5 PD, // 24 - INT0 PD, // 25 // LCD_Seg21 PD, // 26 // LCD_Seg20 PD, // 27 // LCD_Seg19 PD, // 28 // LCD_Seg18 PD, // 29 // LCD_Seg17 PD, // 30 // LCD_Seg16 PD, // 31 // LCD_Seg15 PE, // 32 - RXD - PCINT0 // Header Pin7 PE, // 33 - TXD - PCINT1 // Header Pin6 PE, // 34 - PCINT2 // Header Pin2 PE, // 35 - PCINT3 // Activate reflective sensor PE, // 36 - SCL - PCINT4 // Reflective sensor output PE, // 37 - SDA - PCINT5 PE, // 38 - PCINT6 PE, // 39 - PCINT7 PF, // 40 - A0 PF, // 41 - A1 PF, // 42 - A2 // NTC measurement. PF, // 43 - A3 // Activate NTC divider bridge PF, // 44 - A4 - TCK // Header Pin4 PF, // 45 - A5 - TMS // Header Pin3 PF, // 46 - A6 - TDO // Header Pin5 PF, // 47 - A7 - TDI // Header Pin8 PG, // 48 // LCD_Seg14 PG, // 49 // LCD_Seg13 PG, // LCD_Seg4 PG, // H-Bridge 3 PG, // 52 // H-Bridge 4 NOT_A_PORT, NOT_A_PORT, NOT_A_PORT, }; const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { _BV(0), /* 0, port A */ _BV(1), _BV(2), _BV(3), _BV(4), _BV(5), _BV(6), _BV(7), _BV(0), /* 8, port B */ _BV(1), _BV(2), _BV(3), _BV(4), _BV(5), _BV(6), _BV(7), _BV(0), /* 16, port C */ _BV(1), _BV(2), _BV(3), _BV(4), _BV(5), _BV(6), _BV(7), _BV(0), /* 24, port D */ _BV(1), _BV(2), _BV(3), _BV(4), _BV(5), _BV(6), _BV(7), _BV(0), /* 32, port E */ _BV(1), _BV(2), _BV(3), _BV(4), _BV(5), _BV(6), _BV(7), _BV(0), /* 40, port F */ _BV(1), _BV(2), _BV(3), _BV(4), _BV(5), _BV(6), _BV(7), _BV(0), /* 48, port G */ _BV(1), _BV(2), _BV(3), _BV(4), NOT_A_PIN, NOT_A_PIN, NOT_A_PIN, }; const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { NOT_ON_TIMER, /* 0 - PA0 */ NOT_ON_TIMER, /* 1 - PA1 */ NOT_ON_TIMER, /* 2 - PA2 */ NOT_ON_TIMER, /* 3 - PA3 */ NOT_ON_TIMER, /* 4 - PA4 */ NOT_ON_TIMER, /* 5 - PA5 */ NOT_ON_TIMER, /* 6 - PA6 */ NOT_ON_TIMER, /* 7 - PA7 */ NOT_ON_TIMER, /* 8 - PB0 */ NOT_ON_TIMER, /* 9 - PB1 */ NOT_ON_TIMER, /* 10 - PB2 */ NOT_ON_TIMER, /* 11 - PB3 */ TIMER0A, /* 12 - PB4 */ TIMER1A, /* 13 - PB5 */ TIMER1B, /* 14 - PB6 */ TIMER2A, /* 15 - PB7 */ NOT_ON_TIMER, /* 16 - PC0 */ NOT_ON_TIMER, /* 17 - PC1 */ NOT_ON_TIMER, /* 18 - PC2 */ NOT_ON_TIMER, /* 19 - PC3 */ NOT_ON_TIMER, /* 20 - PC4 */ NOT_ON_TIMER, /* 21 - PC5 */ NOT_ON_TIMER, /* 22 - PC6 */ NOT_ON_TIMER, /* 23 - PC7 */ NOT_ON_TIMER, /* 24 - PD0 */ NOT_ON_TIMER, /* 25 - PD1 */ NOT_ON_TIMER, /* 26 - PD2 */ NOT_ON_TIMER, /* 27 - PD3 */ NOT_ON_TIMER, /* 28 - PD4 */ NOT_ON_TIMER, /* 29 - PD5 */ NOT_ON_TIMER, /* 30 - PD6 */ NOT_ON_TIMER, /* 31 - PD7 */ NOT_ON_TIMER, /* 32 - PE0 */ NOT_ON_TIMER, /* 33 - PE1 */ NOT_ON_TIMER, /* 34 - PE2 */ NOT_ON_TIMER, /* 35 - PE3 */ NOT_ON_TIMER, /* 36 - PE4 */ NOT_ON_TIMER, /* 37 - PE5 */ NOT_ON_TIMER, /* 38 - PE6 */ NOT_ON_TIMER, /* 39 - PE7 */ NOT_ON_TIMER, /* 40 - PF0 */ NOT_ON_TIMER, /* 41 - PF1 */ NOT_ON_TIMER, /* 42 - PF2 */ NOT_ON_TIMER, /* 43 - PF3 */ NOT_ON_TIMER, /* 44 - PF4 */ NOT_ON_TIMER, /* 45 - PF5 */ NOT_ON_TIMER, /* 46 - PF6 */ NOT_ON_TIMER, /* 47 - PF7 */ NOT_ON_TIMER, /* 48 - PG0 */ NOT_ON_TIMER, /* 49 - PG1 */ NOT_ON_TIMER, /* 50 - PG2 */ NOT_ON_TIMER, /* 51 - PG3 */ NOT_ON_TIMER, /* 52 - PG4 */ NOT_ON_TIMER, /* 53 - PG5 dose not exist*/ NOT_ON_TIMER, /* 54 - PG6 dose not exist*/ NOT_ON_TIMER /* 55 - PG7 dose not exist*/ }; #endif // These serial port names are intended to allow libraries and architecture-neutral // sketches to automatically default to the correct port name for a particular type // of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, // the first hardware serial port whose RX/TX pins are not dedicated to another use. // // SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor // // SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial // // SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library // // SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. // // SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX // pins are NOT connected to anything by default. #define SERIAL_PORT_MONITOR Serial #define SERIAL_PORT_HARDWARE Serial #endifDISCLAIMER: The previous file has been created by myself by mixing several sources.I am notan arduino nor AVR expert, and I do not guarantee that everything is correct. Specificaly, i have some doubt about the pin change interupts... to be tested and improved.
So once this file has been created, i can start arduino and create a simple "blink" sketch.
/* Blink Turns on an LED on for one second, then off for one second, repeatedly. This example code is in the public domain. */ int led = 34; // pin 34 = PE2, a pin exposed on the connector of the TRV. // the setup routine runs once when you press reset: void setup() { // initialize the digital pin as an output. pinMode(led, OUTPUT); } // the loop routine runs over and over again forever: void loop() { digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(led, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second }Menu Tool / Card Type, i select the HR25 entry. Then, i select file/ upload with programmer and voila !
The sketch compile and is loaded through the isp pins.
Then i can see the PE2 pin blinking... Howeer, the frequecy is not correct . Instead of blinking every 1s I have a blink every 8seconds... i guess i have a problem of frequency scaling.... to be investigated but it's a good start ! -
The fuses of th HR25 atmega are:
E:FD, H:91, L:62
If i trust the AVR duse calc: http://www.engbedded.com/fusecalc/
This means that the 8-divider is applied on the clock... this might explain the behavious seen above.So i changed the CKDIV8 bit:
avrdude -c usbasp -p m329p -U lfuse:w:0xe2:mand voila the pin 34 , blink à 1Hz.
Frequency problem solved. -
OK, some news....
I have connected a rf24 module to the external header, hoping to drive it with softSPI (in order to limit internal modification of the valve).While compiling a simple mysensor sketch, i can see several issues with the libraries Lowpower.h and PinchangeInt.h.... these libraries are very MCU-dependant and are not compiling. It is probably doable to modify them in order to upport the 329p, but it is out of my field of competence. I don't really understand the internals of theses libs.
If someone can help, it will be apreciated. -
@hek said:
These dependencies has been removed in the development branch.
Is that sure ? I have not tried to compile dev branch yet, but i still find a reference to lowpower in Mysensor.h :
#ifdef __cplusplus #include <Arduino.h> #include <SPI.h> #include "utility/LowPower.h" #endif -
@hek said:
These dependencies has been removed in the development branch.
Is that sure ? I have not tried to compile dev branch yet, but i still find a reference to lowpower in Mysensor.h :
#ifdef __cplusplus #include <Arduino.h> #include <SPI.h> #include "utility/LowPower.h" #endifSorry.. I only read PinChangeInt. Still a Lowpower dependecy if you want to use the sleep functions.
Might be good to make this as a "driver" as well in the future. But it will be hard because it is relatively hardware dependent if you want to wake up on external triggers.
-
Sorry.. I only read PinChangeInt. Still a Lowpower dependecy if you want to use the sleep functions.
Might be good to make this as a "driver" as well in the future. But it will be hard because it is relatively hardware dependent if you want to wake up on external triggers.
-
Other general question:
At this stage, is the "dev" branch compatible with a "stable" gateway and "stable" nodes ? -
Hello Lucas,
Last year , i did not achieve to run a sketch on the HR25. I remain convinced that it should be doable, but i am not enough aware of the inner details of the MCU / Arduino.
also, my job has become a lot more time consuming, and i have not been able to spend time on this project for several months.If someone want to take over from here, i would be very happy.