Mega to UNO conversion

Go To Last Post
52 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi i have a sketch working on a arduino Mega, it uses a rewritten hardwareserial library.
Now i want to upload it on my UNO, and yes i have rewritten the code because only one serial is available on the UNO (i used debugging over softwareserial and a USB/serial cable).

 

It's a program to read from a EMS-Buderus bus, the data seem to have a 11 bit null as end-of-packet indicator, the program i found uses that to split the messages with a modified hardwareserial called nefitserial. It seems to be written for Atmega8. Now i would like to rewrite it so i can use it on my UNO. But i can't get it to work, all registers stay empty so i think the data isn't decoded properly.

I think there are some alternations made in the hardwareserial that are not compatible with my UNO, i think it has to anything with different kinds of (registers/UCSR0A/UDR0 stuff)
Is there someone who knows how this works and who can check the modified hardwareserial library for me.

I realy like to get it working on my UNO instead of Mega.

Info about the data messages:

https://emswiki.thefischer.net/d...

Attachment(s): 

Last Edited: Tue. May 23, 2017 - 03:09 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Both the M2560 (used in the MEGA) and the M328P (used in the UNO) have a USART0, so should be compatible, can you post what error messages you are getting?

 

Jim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes that's it. It compiles and uploads just fine. Only the data isn't read or decoded. My debugging shows empty registers so there is some part of the code what doesn't work. But can't figure out where.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is the correct output. But mine stay empty (0)

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
void setup(){
  nefitSerial1.begin(9700);
  

That is is ODD baud rate, is this a typo? 

 

Jim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Don't know that's how i found it but I have seen 9600 also. Will try 9600 on the mega in a bit. Just to see if it also works. On the uno i have tried it already but thats not the problem it still doesn't work.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

so 9600 works on mega, so i think it was a typo of the original creator

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, so it's still not working on the UNO, is that correct?   Can you post a picture of the setup?

Double check you have the Tx/Rx pins connected correctly, usually it's TX -> RX and RX <- TX, not TX -> TX, Rx <- RX,  with a common gnd.

Do you have a scope available?  if so, connect it to the TX and then the RX lines and look for activity with the program running.

 

Jim

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

setup is simple only three wires. and use the same setup for UNO as for Mega only Mega uses Rx pin 19 and UNO pin 0.

The hardware circuit to make the bus signal TTL has +5V and Ground from arduino, and has a Rx pin to go to arduino. Thats it actually.

Somehow in the library it seems that the arduino use some registers, aparently there's my problem but UNO uses different then stated in the library,i have not that much coding experience to figure it out.

I think somewhere in (UDR0, USART or RXC) statements.

 

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sorry no answers to your questions:

No still not working on UNO.

RX ->TX all possible combinations tried.

No scope.

 

Also tried on arduino micro, but it doesn't compile due to nefitSerial not declared. While i'm using same sketch as Mega cause micro can use Serial1 and Serial. Strange......(somehow the code or library declares board as Atmega8 maybe?????)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No, if it did that, then the register names would not match and you would get compiler errors. 

 

I'm confused, are you using the same sketch on the Mega as on the UNO?

 

Jim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

in general yes:

MEGA has nefitSerial (debug output to serial monitor) and nefitSerial1 (19rx)

UNO has nefitSerial(pin0 rx) and i made a softwareserial at pin 10/11 for debugging output.

tried also with uno direct output to esp8266 chip and still regs are empty.

 

maybe only nefitSerial(x) works????

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
// Set to "1" when debugging
// If enabled, the Arduino sends the decoded values over the Serial port.
#define DEBUG 1

In your example code above DEBUG is set to 1, set this to 0 and see what happens,.....    since you use softserial for debug, this may be interfering with the use of USART0 in the UNO version.

 

Jim

edit: added UNO version.

Last Edited: Tue. May 23, 2017 - 06:25 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i ripped the whole If Debug out of the sketch.

 
#define NEFIT_REG_MAX  17
#include <NefitSerial.h>
#include <UnoWiFiDevEd.h>

PROGMEM const unsigned char regNefitCoding[]={

0x08,0x18,0x01,0x05,          //#1   0 temperature water out (uitgaand) x 10
0x08,0x18,0x04,0x01,          //#2   1 burner power
0x08,0x18,0x07,0x00,          //#3   2 burner of/off
0x08,0x18,0x07,0x50,          //#4   3 heating pump on/off
0x08,0x18,0x07,0x60,          //#5   4 tap water heating on/off
0x08,0x18,0x0B,0x05,          //#6   5 boiler temperature x 10
0x08,0x18,0x0D,0x05,          //#7   6 temperature water in (cvreturn) x 10
0x08,0x18,0x11,0x06,          //#8   7 water pressure x 10
0x08,0x18,0x12,0x02,          //#9   8 status code 1st letter
0x08,0x18,0x13,0x02,          //#10  9 status code 2nd letter
0x08,0x34,0x01,0x05,          //#11 10 tap water temperature x 10
0x08,0x34,0x05,0x50,          //#12 11 heater boiler on/off (not always available)
0x17,0x91,0x01,0x04,          //#13 12 setpoint room temperature x 2
0x17,0x91,0x02,0x05,          //#14 13 room temperature x 10
0x17,0xA8,0x17,0x81,          //#15 14 setting 0=low, 1=manual, 2=clock
0x17,0xA8,0x1C,0x84,          //#16 15 overruled clock setting x 2 ( 0 = not overruled)
0x17,0xA8,0x1D,0x84           //#17 16 manual setpoint temperature x 2
};

void printbuffer(char * buffer, int len );

char buffer[32];                              // frame buffer
int nefitRegister[NEFIT_REG_MAX];             // index number see above

long lastTime = 0;  
long interval = 10000;

// Calculate CRC for buffer
uint8_t nefit_ems_crc( char * buffer, int len ){
  uint8_t i,crc = 0x0;
  uint8_t d;
  for(i=0;i<len-2;i++){
    d = 0;
    if ( crc & 0x80 ){
      crc ^= 12;
      d = 1;
    }
    crc  = (crc << 1)&0xfe;
    crc |= d;
    crc ^= buffer[i];
  }
  return crc;
}

// CRC check 
boolean crcCheckOK(char * buffer, int len ){
  int crc = nefit_ems_crc(buffer, len );
  boolean crcOK= (crc==(uint8_t)buffer[len-2]);
  return crcOK;
}

// Read one bus frame, return number of read bytes
int readBytes(char * buffer){
  int ptr = 0;

  while(nefitSerial.available()){
    if((uint8_t)nefitSerial.peek()==0){
      uint8_t temp = nefitSerial.read();                    // skip zero's
    } else { break;}
  }

  while((!nefitSerial.frameError())&&ptr<32){          // read data until frame-error
     if(nefitSerial.available()){
      buffer[ptr]=nefitSerial.read();
      ptr++;
     }
  }
  nefitSerial.flush();
  return ptr;
}


// Read a register value from frame-buffer, decide if necessary and return as int
int getValue(char * buffer, byte offset, byte vartype){
  int result;
  uint8_t type = vartype & 0x0F;
  switch (type){
    case 0:     //boolean
      result = bitRead(buffer[offset],(vartype&0x70)>>4);
      break;
    case 1:     //byte
//      result = (uint8_t)buffer[offset];
//      break;
    case 2:     //ascii
//      result = (uint8_t)buffer[offset];
//                        break;
    case 4:     //byte x 2
//      result = (uint8_t)buffer[offset];
//      break;
    case 6:     //byte x 10
      result = (uint8_t)buffer[offset];
                        break;
    case 3:     //int
//      result = getDoubleByte(buffer,offset);
//      break;
    case 5:     //int x 10
        result = buffer[offset]<<8;
      result = result + (uint8_t)buffer[offset+1];
      break;

  }
    return result;
}

// Decode frame with help of the table and load register
void nefitFrame2register(char * buffer, int len){
  byte sender, message;
  int register_data, difference;
  uint8_t offset, vartype;
  for(uint8_t i=0;i<((NEFIT_REG_MAX)*4);i=i+4){
    sender = pgm_read_byte_near(regNefitCoding+i);
    message = pgm_read_byte_near(regNefitCoding+1+i);
    if ((sender<=(uint8_t)buffer[0]) && (message<=(uint8_t)buffer[2])){
      offset = pgm_read_byte_near(regNefitCoding+2+i);
      if ((sender==(uint8_t)buffer[0]) && (message==(uint8_t)buffer[2])&&(offset>=(uint8_t)buffer[3])){
        offset = offset - (uint8_t)buffer[3]+4;       // rekening houden met lange frames (gesplitst)
        if (offset<len){
           vartype = pgm_read_byte_near(regNefitCoding+3+i);
           register_data = getValue(buffer,offset,vartype);
           if (register_data != nefitRegister[i/4])
             {
                nefitRegister[i/4] = register_data;
             }
        }
      }
    }else {break;}
  }
 return;
}



// -----------------------------------------------------------------------------------------------------------------

void setup(){
  nefitSerial.begin(9600);
  Ciao.begin();
  Ciao.println("Start up");
  Ciao.print("Welcome");



  for (char i=0;i<=NEFIT_REG_MAX;i++) {
    nefitRegister[i]=0;
  }
}


// -----------------------------------------------------------------------------------------------------------------

void loop(){
  int ptr;

 if (nefitSerial.available()){  // check if we need to read
  ptr = readBytes(buffer);
  if (ptr>4){
    if (crcCheckOK(buffer,ptr)){
      nefitFrame2register(buffer,ptr);
    }
  }
    }


    if(millis() - lastTime > interval) {
    lastTime = millis(); 
   for (int i = 0; i<=NEFIT_REG_MAX; i++){
   Ciao.print("nefitRegister["); Ciao.print(i); Ciao.print("]: ");
   Ciao.println(nefitRegister[i]);}
  Ciao.println("------------------------");
  Ciao.println("NEFIT EMS bus:");
  
  Ciao.print("cv water output: ");
  Ciao.println((float)nefitRegister[0]/10,1);      

  Ciao.print("burner power: ");
  Ciao.println((float)nefitRegister[1],1);      

  Ciao.print("burner on/off: ");
  Ciao.println((float)nefitRegister[2],DEC);   // burner  

  Ciao.print("cv pump on/off: ");
  Ciao.println((float)nefitRegister[3],DEC);   //cv pump  
 
  Ciao.print("hot water on/off: ");
  Ciao.println((float)nefitRegister[4],DEC);    

  Ciao.print("boiler temp: ");
  Ciao.println((float)nefitRegister[5]/10,1);    //keteltemp
  
  Ciao.print("cv return temp: ");
  Ciao.println((float)nefitRegister[6]/10,1);    //waterterug temp
  
  Ciao.print("waterpressure: ");
  Ciao.println((float)nefitRegister[7]/10,1);    // waterpressure

  Ciao.print("statuscode: ");
  Ciao.print((char)nefitRegister[8]);    
  Ciao.println((char)nefitRegister[9]);  
  
  Ciao.print("hot water temp: ");
  Ciao.println((float)nefitRegister[10]/10,1);   //hotwatertemp

  Ciao.print("boiler heater on/off: ");
  Ciao.println((float)nefitRegister[11],DEC);  

  //Ciao.print(",");
  //Ciao.print(nefitRegister[14],DEC);           //thermostat 0=low, 1=manual, 2=auto

  Ciao.println("END");
  Ciao.println("------------------------");
  Ciao.println("------------------------");
}
 
    
}//end void loop

Where Ciao is output to WIFI Console monitor

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

After some googling found some more info, could the clockspeed be a problem?? 8MHz/16MHz?

Or the baudrate formula in the library??

Last Edited: Tue. May 23, 2017 - 08:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The art of debugging begins with breaking down where the problem is by adding some print statements after each function call to see what is returned.

Since you are not getting any data output, check for data input, do you rx any data into the buffer, if so, what data....... ect...

 

Walk down the program until you find where it is not working.....  i.e.  it gets a buffer of data, but does not pass crc....  as an example....

 

Report back what you find.

 

Jim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But everything is written in a library, so where do i put the debugmessages? Could you help me with that? And where do i need to debug to since i have only one serial output.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The primary rule for electronic design is "if it works, don't f**k with it".   According to the original post, there is a working version of the code that the poster wishes to move from the Arduino Mega to the Arduino UNO.  An attempt was made to adapt the working code from the Mega to UNO, but it failed.

 

There are two ways to approach this problem.  The first is to spend hours thinking, testing, experimenting, documenting, studying, whatever.   The other approach is to just spend the $8.59 (@7 Euros) and just buy an extra Arduino Mega and run the working code on it.  Here is a link for a $8.59 Mega with free shipping:

http://www.ebay.com/itm/Mega-256...

 

The advantage to spending hours thinking, testing, experimenting, documenting, studying, whatever on trying to understand why the code doesn't work on a UNO is that you ~might~ develop an insight into the operation of the code to the extent that you can fix the next thing that goes wrong with it.  This is assuming that the code that works on the original MEGA with work on the replacement $8.59 Arduino Mega2560.  If it does, then go to some other problem because you solved this problem by applying the primary rule described above.  If it doesn't work on the new Mega, then spend hours thinking, testing, experimenting, documenting, studying, whatever on trying to understand why the code doesn't work.

 

What is wrong with this approach besides that it doesn't work well when you're an employee and your boss insists that you make it work on a UNO?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Since i like to upload my data to my domoticz server i like to use my UNO with integrated WiFi. If i use my Mega then i need to buy another ESP8266 module while i have the UNO laying around.

So why spent Money if you don't need to.

I think it is a small error in the library which can easily be fixed, just need to find it.

So why spend money while it is a software related problem?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Matje i must have to buy an esp8266 and a arduino micro. Maybe that works.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

When debugging, it is best to only make one change at a time, if it fails you can return to what works, then try again with another angle.

In your case your making two changes at once, switching platforms MEGA to UNO and changing serial ports. 

Since the target only has one USART, try adapting the code for the MEGA to use only one h/w USART. Once that works, it should port easily.

 

Jim

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

delchrys wrote:
So why spent Money if you don't need to.

That depends on how you value your time...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So first I'll have to try to use mega serial0 pin0/1 for the input and debugging through usb/serial cable. Then port it to uno.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm noe trying to rewrite all to the hardwareserial library. Once it works properly then i will try to port it to Uno. I don't care about hardwareserial original to be modified. I will use it only for this project.
Some of the store char functions in the original modified nefitserial are a bit unclear for me where to put it in hardwareserial.cpp or .h. have to fivure that one out. Someone who can give me any pointer on that?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#if !defined(USART0_RX_vect) && defined(USART1_RX_vect)
// do nothing - on the 32u4 the first USART is USART1
#else
#if !defined(USART_RX_vect) && !defined(USART0_RX_vect) && \
!defined(USART_RXC_vect)
#error "Don't know what the Data Received vector is called for the first UART"
#else
void nefitSerialEvent() __attribute__((weak));
void nefitSerialEvent() {}
#define nefitSerialEvent_implemented
#if defined(USART_RX_vect)
ISR(USART_RX_vect)
#elif defined(USART0_RX_vect)
ISR(USART0_RX_vect)
#elif defined(USART_RXC_vect)
ISR(USART_RXC_vect) // ATmega8
#endif
{
#if defined(UDR0)
bool fe = bitRead(UCSR0A, FE0);
unsigned char c = UDR0;
store_char(c, fe, &nefitSerial);
#elif defined(UDR)
bool fe = bitRead(UCSRA, FE);
unsigned char c = UDR;
store_char(c, fe, &nefitSerial);
#else
#error UDR not defined
#endif
}
#endif
#endif
#if defined(USART1_RX_vect)
void nefitSerialEvent1() __attribute__((weak));
void nefitSerialEvent1() {}
#define nefitSerialEvent1_implemented
ISR(USART1_RX_vect)
{
bool fe = bitRead(UCSR1A, FE1);
unsigned char c = UDR1;
store_char(c, fe, &nefitSerial1);
}
#endif
#if defined(USART2_RX_vect) && defined(UDR2)
void nefitSerialEvent2() __attribute__((weak));
void nefitSerialEvent2() {}
#define nefitSerialEvent2_implemented
ISR(USART2_RX_vect)
{
bool fe = bitRead(UCSR2A, FE2);
unsigned char c = UDR2;
store_char(c, fe, &nefitSerial2);
}
#endif
#if defined(USART3_RX_vect) && defined(UDR3)
void nefitSerialEvent3() __attribute__((weak));
void nefitSerialEvent3() {}
#define nefitSerialEvent3_implemented
ISR(USART3_RX_vect)
{
bool fe = bitRead(UCSR3A, FE3);
unsigned char c = UDR3;
store_char(c, fe, &nefitSerial3);
}
#endif

This part I meant.

(edit: code properly displayed) ;)

 

Last Edited: Sat. May 27, 2017 - 06:43 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You seem to have forgotten how to post code properly - you've managed it OK before ...

Last Edited: Thu. May 25, 2017 - 01:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry for posting code that way but was on mobile so can not post code properly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But anyone who can give me some pointers?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How about 

int *p, *q;

David

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

DAFlippers wrote:

How about 

int *p, *q;

David


I do not understand what you mean by that can you explain

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

you asked for some pointers.... 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Some more pointers

 

Image result for pointers

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Maybe soms hints or tips or help then? $orry for being $eriou$.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The key one was here: http://www.avrfreaks.net/comment... - note that prints are not the only way

 

Debugging in general:

 

http://www.8052.com/faqs/120313

 

http://www.ganssle.com/articles/...

 

#HowToDebug

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry for being unclear. I was more asking help on the little code which I posted improperly. It's the last piece of code I have to get to work. But where do I place the ISR's in the hardwareserial library?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So i think the problem lies with using Serial(0) as the input for the bus message. When using this nefitSerial instead of nefitSerial1/2/3 as the input the code goes wrong and registers stay empty.

Someone who has an explanation for it. Or is it impossible to get it working on pin0/1 cause of the interference with Serial Monitor although i do not use it.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry for the many questions but isn't it possible to rewrite the sketch and not using the library anymore?? I'm not that in to the bits and stuff but from what i've read, the only odd part is that the message is ended bij aa 11bit 'null', so i only need to detect that and everything before the end/break should be the message.

Maybe this is possible by using ISR's and direct register coding like some DMX-sketches i've seen.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think you need to RTFM - check the library documentation:

This sketch uses the Arduino Mega and the Wiznet 5100 ethernet shield. You can also use another Arduino like the Uno but that one only has one hardware serial port.

Serial1 is used for the EMS module. Serial is used to debug the output to PC. EMS serial works with 9700 Baudrate and 8N1. For sending data to the EMS bus you need a modified Serial library. It's included in the project.

Arduino Mega:

  • Serial on pins 0 (RX) and 1 (TX),
  • Serial1 on pins 19 (RX) and 18 (TX),
  • Serial2 on pins 17 (RX) and 16 (TX),
  • Serial3 on pins 15 (RX) and 14 (TX).

Arduino non-Mega: You cannot use Serial1, so you need to use Serial, which does not allow for debugging via serial.

This tells you the library will work with the Uno but you cannot use serial debugging.  You took that in and are looking at soft serial  but you think there may be a baudrate/CPU clock problem.  Well check out post #6 where you changed the Baudrate to 9600 when Jim asked if 9700 was correct.  What you should have done was to check the documentation and also the setup in the sample sketch:

 

void setup(){

  nefitSerial1.begin(9700);

  

#if DEBUG  

  nefitSerial.begin(9600);

  nefitSerial.println("Nefit to Domoticz");

#endif  



  Ethernet.begin(mac, ip);



#if DEBUG

  nefitSerial.print("IP address: ");

  nefitSerial.println(ip);

#endif  



  for (char i=0;i<=NEFIT_REG_MAX;i++) {

    nefitRegister[i]=0;

  }

}

The Baudrate needs to be 9700 for the Nefit/Buderus EMS protocol.  

 

 

David 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried almost every possible baud rate combo and still it won't work.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

so post your latest, unmodified, code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Latest code is just the example sketch only changed nefitSerial1 to nefitSerial and debug code changed from nefitserial to ciao.print because that's the Wi-Fi console of my uno.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why not post the code?  Then we could see if there is anything you have missed.

 

David

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Wil do tomorrow.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


/*
/* EMS bus decoder to Domoticz sketch for Arduino with Ethernet module
 * * Version 1.0 Minimal - Github - May 2017
 * 
 * Copyright (c) 2017 - 'bbqkees' @ www.domoticz.com/forum
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * 
 * Legal Notices
 * 'Worcester', 'Bosch Group', 'Buderus' and 'Nefit' are brands of Bosch Thermotechnology.
 * All other trademarks are the property of their respective owners.

 * last edit  :  16-MAY-2017
 * 
 * 16-MAY-2017:  Minimal version for read only.
 * 17-JAN-2017:  Github version 1.0
 * 16-NOV-2016:  Data only sent if value has changed.
 *               #if DEBUG added to print debug data over Serial0 port. 
 * 15-NOV-2016:  Initial version
 * 
 * What does it do?
 * This sketch reads the EMS interface data and depending on the format decodes the data and puts it in variables.
 * You can then send the values via HTTP GET requests to Domoticz or do whatever you want with it.
 * Usage is of course not limited to Domoticz, you can extract the decoding part for other purposes.
 * 
 * Most boilers send out datagrams every few seconds, these will be read automatically by this sketch.
 * 
 * As I am Dutch, some variables might be in partial Dutch instead of English.
 * F.i. 'CV' is 'Centrale Verwarming', which means 'Central Heating'. So if you see 'cv' think 'ch'.
 * Same for 'WW" which is 'Warm Water' which translates to 'hot tap water' in English.
 * However I translated all the comments to English.
 * 
 * If you have question about this sketch and its methods, please ask me on the Domoticz forum.
 */
 
#include <UnoWiFiDevEd.h>  
#define NEFIT_REG_MAX	17
 
#include <NefitSerial.h>
#include <SPI.h>


/*
* The following table is used in converting the register to and from the Nefit bus messages.
* It also supplies the encoding it is in.
* 
* Format: <transmitter ID>,<frametype>,<data-offset>,<vartype>     // data-offset start at byte 4
* vartype bit 3-0 	= 0 boolean (bitnr in bit 6-4)
*			= 1 byte
*			= 2 ascii
*			= 3 int
*			= 4 byte x 2 (For reading value divide by two)
*			= 5 int x 10 (for reading value divide by ten)
*     = 6 byte x 10 (for reading value divide by ten)
*
* Transmitter ID 0x08 is the listening address for the EMS bus.
* The boiler will provide this data.
* Transmitter ID 0x17 is from the RC20 type thermostat. 
* You will onyl see this data if you have this thermostat.
* Otherwise you need to check http://emswiki.thefischer.net/ for your thermostat.
* 
* You can only change the setpoint etc if you have connected the thermostat to the bus.
* 
*/

PROGMEM const unsigned char regNefitCoding[]={

0x08,0x18,0x01,0x05,					//#1   0 temperature water out (uitgaand) x 10
0x08,0x18,0x04,0x01,					//#2   1 burner power
0x08,0x18,0x07,0x00,					//#3   2 burner of/off
0x08,0x18,0x07,0x50,					//#4   3 heating pump on/off
0x08,0x18,0x07,0x60,					//#5   4 tap water heating on/off
0x08,0x18,0x0B,0x05,					//#6   5 boiler temperature x 10
0x08,0x18,0x0D,0x05,					//#7   6 temperature water in (cvreturn) x 10
0x08,0x18,0x11,0x06,					//#8   7 water pressure x 10
0x08,0x18,0x12,0x02,					//#9   8 status code 1st letter
0x08,0x18,0x13,0x02,					//#10  9 status code 2nd letter
0x08,0x34,0x01,0x05,					//#11 10 tap water temperature x 10
0x08,0x34,0x05,0x50,					//#12 11 heater boiler on/off (not always available)
0x17,0x91,0x01,0x04,					//#13 12 setpoint room temperature x 2
0x17,0x91,0x02,0x05,					//#14 13 room temperature x 10
0x17,0xA8,0x17,0x81,					//#15 14 setting 0=low, 1=manual, 2=clock
0x17,0xA8,0x1C,0x84,					//#16 15 overruled clock setting x 2 ( 0 = not overruled)
0x17,0xA8,0x1D,0x84					  //#17 16 manual setpoint temperature x 2
};

void printbuffer(char * buffer, int len );

char buffer[32];                				      // frame buffer
int nefitRegister[NEFIT_REG_MAX];	            // index number see above

long lastTime = 0;  
long interval = 10000;
long lastTimeeth = 0;  
long intervaleth = 30000;

int IDXcvpressure = 000; // Set here your own Domoticz ID's
int IDXburnerpower = 000;
int IDXburner = 000;
int IDXboiler = 000;
int IDXcvreturn = 000;
int IDXsupply = 000;
int IDXhotwater = 000;
int IDXcvpump = 000;

float lastcvpressure = 0;
float lastburnerpower = 0;
float lastburner = 0;
float lastboiler = 0;
float lastcvreturn = 0;
float lastsupply = 0;
float lasthotwater = 0;
float lastcvpump = 0;

String burnerstatus = "Off";
String cvpumpstatus = "Off";
String hotwaterstatus = "Off";



// Calculate CRC for buffer
uint8_t nefit_ems_crc( char * buffer, int len ){
  uint8_t i,crc = 0x0;
  uint8_t d;
  for(i=0;i<len-2;i++){
    d = 0;
    if ( crc & 0x80 ){
      crc ^= 12;
      d = 1;
    }
    crc  = (crc << 1)&0xfe;
    crc |= d;
    crc ^= buffer[i];
  }
  return crc;
}

// CRC check 
boolean crcCheckOK(char * buffer, int len ){
  int crc = nefit_ems_crc(buffer, len );
  boolean crcOK= (crc==(uint8_t)buffer[len-2]);
  return crcOK;
}

// Read one bus frame, return number of read bytes
int readBytes(char * buffer){
  int ptr = 0;

  while(nefitSerial.available()){
    if((uint8_t)nefitSerial.peek()==0){
      uint8_t temp = nefitSerial.read();                    // skip zero's
    } else { break;}
  }

  while((!nefitSerial.frameError())&&ptr<32){          // read data until frame-error
     if(nefitSerial.available()){
      buffer[ptr]=nefitSerial.read();
      ptr++;
     }
  }
  nefitSerial.flush();
  return ptr;
}


// Read a register value from frame-buffer, decide if necessary and return as int
int getValue(char * buffer, byte offset, byte vartype){
  int result;
  uint8_t type = vartype & 0x0F;
	switch (type){
		case 0:			//boolean
			result = bitRead(buffer[offset],(vartype&0x70)>>4);
			break;
		case 1:			//byte
//			result = (uint8_t)buffer[offset];
//			break;
		case 2:			//ascii
//			result = (uint8_t)buffer[offset];
//                        break;
		case 4:			//byte x 2
//			result = (uint8_t)buffer[offset];
//			break;
		case 6:			//byte x 10
			result = (uint8_t)buffer[offset];
                        break;
		case 3:			//int
//			result = getDoubleByte(buffer,offset);
//			break;
		case 5:			//int x 10
		    result = buffer[offset]<<8;
			result = result + (uint8_t)buffer[offset+1];
			break;

	}
    return result;
}

// Decode frame with help of the table and load register
void nefitFrame2register(char * buffer, int len){
  byte sender, message;
  int register_data, difference;
  uint8_t offset, vartype;
  for(uint8_t i=0;i<((NEFIT_REG_MAX)*4);i=i+4){
    sender = pgm_read_byte_near(regNefitCoding+i);
    message = pgm_read_byte_near(regNefitCoding+1+i);
    if ((sender<=(uint8_t)buffer[0]) && (message<=(uint8_t)buffer[2])){
      offset = pgm_read_byte_near(regNefitCoding+2+i);
      if ((sender==(uint8_t)buffer[0]) && (message==(uint8_t)buffer[2])&&(offset>=(uint8_t)buffer[3])){
        offset = offset - (uint8_t)buffer[3]+4;       // rekening houden met lange frames (gesplitst)
        if (offset<len){
           vartype = pgm_read_byte_near(regNefitCoding+3+i);
           register_data = getValue(buffer,offset,vartype);
           if (register_data != nefitRegister[i/4])
             {
                nefitRegister[i/4] = register_data;
             }
        }
      }
    }else {break;}
  }
 return;
}


// -----------------------------------------------------------------------------------------------------------------

void setup(){
  nefitSerial.begin(9700);
  Wifi.begin();
  Wifi.print("Nefit to Domoticz");




  for (char i=0;i<=NEFIT_REG_MAX;i++) {
    nefitRegister[i]=0;
  }
}


// -----------------------------------------------------------------------------------------------------------------

void loop(){
  int ptr;

 if (nefitSerial.available()){  // check if we need to read
	ptr = readBytes(buffer);
	if (ptr>4){
	  if (crcCheckOK(buffer,ptr)){
	    nefitFrame2register(buffer,ptr);
	  }
	}
    }


    if(millis() - lastTime > interval) {
    lastTime = millis(); 
   for (int i = 0; i<=NEFIT_REG_MAX; i++){
   Wifi.print("nefitRegister["); Wifi.print(i); Wifi.print("]: ");
   Wifi.println(nefitRegister[i]);}
  Wifi.print("------------------------");
  Wifi.println("NEFIT EMS bus:");
  
  Wifi.print("cv water output: ");
  Wifi.println((float)nefitRegister[0]/10,1);      

  Wifi.print("burner power: ");
  Wifi.println((float)nefitRegister[1],1);      

  Wifi.print("burner on/off: ");
  Wifi.println((float)nefitRegister[2],DEC);   // burner  

  Wifi.print("cv pump on/off: ");
  Wifi.println((float)nefitRegister[3],DEC);   //cv pump  
 
  Wifi.print("hot water on/off: ");
  Wifi.println((float)nefitRegister[4],DEC);    

  Wifi.print("boiler temp: ");
  Wifi.println((float)nefitRegister[5]/10,1);    //keteltemp
  
  Wifi.print("cv return temp: ");
  Wifi.println((float)nefitRegister[6]/10,1);    //waterterug temp
  
  Wifi.print("waterpressure: ");
  Wifi.println((float)nefitRegister[7]/10,1);    // waterpressure

  Wifi.print("statuscode: ");
  Wifi.print((char)nefitRegister[8]);    
  Wifi.println((char)nefitRegister[9]);  
  
  Wifi.print("hot water temp: ");
  Wifi.println((float)nefitRegister[10]/10,1);   //hotwatertemp

  Wifi.print("boiler heater on/off: ");
  Wifi.println((float)nefitRegister[11],DEC);  

  //Wifi.print(",");
  //Wifi.print(nefitRegister[14],DEC);           //thermostat 0=low, 1=manual, 2=auto

  Wifi.println("END");
  Wifi.println("------------------------");
  Wifi.println("------------------------");
}



    
}//end void loop

So that's about it, could it be the UnoWiFiDevEd library that's bugging my NefitSerial???

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can see you asked this elsewhere https://forum.arduino.cc/index.p...

 

In the first post in both the above and this thread you state: 

 

i have a sketch working on a arduino Mega

Can you confirm that you have real valid data from your boiler - please post some data from the working sketch on the Arduino Mega.

 

David

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It gives me this on the serial monitor

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You posted that in #4. Can you re run to get some new data so we can check the interface is still correct? 

 

David 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually forget it.  I will not look any further into this.  I asked for your sample data and you posted 'your' data........which is available to one and all at https://www.domoticz.com/forum/v... by bbqkees which explains the Dutch text. 

 

You are just wasting people's time.

 

David

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Don't see what the difference is when I use the same sketch. Data stays the same only different numbers.
Do you want raw data or encoded like the one above?
Raw data is just some hex numbers.
On the interface nothing has changed so it still works properly.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I maybe off topic here but on the UNO R3 board that I use the serial pins 1/2 are useless for external serial connection due to the USB interface swamping the RX.

Use Software serial or an equivalent on another set of pins

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So even when not using serial monitor the serial pins are useless? Then the whole library must be rewritten to softwareserial. That's a lot of work.....
Hmm have to find some other workaround then. Might end up using two arduino then.