DFF4.1: Difference between revisions

From KONNEKTING Wiki
Jump to navigation Jump to search
No edit summary
→Help: added details on how to find error with non-switching relais.
 
Line 99: Line 99:


// MCP23017 Output register<->pin map
// MCP23017 Output register<->pin map
#define OA0 0
#define GPA0 0 // E 1
#define OA1 1
#define GPA1 1 // E 0
#define OA2 2
#define GPA2 2
#define OA3 3
#define GPA3 3
#define OA4 4
#define GPA4 4
#define OA5 5
#define GPA5 5
#define OA6 6
#define GPA6 6
#define OA7 7
#define GPA7 7
#define OB0 8
#define GPB0 8
#define OB1 9
#define GPB1 9
#define OB2 10
#define GPB2 10 // B 0
#define OB3 11
#define GPB3 11 // B 1
#define OB4 12
#define GPB4 12 // C 0
#define OB5 13
#define GPB5 13 // C 1
#define OB6 14
#define GPB6 14 // D 0
#define OB7 15
#define GPB7 15 // D 1


#define A_SET  GPB1
#define A_RESET GPB0


#define A_SET   OB1
#define B_SET   GPB3
#define A_RESET OB0
#define B_RESET GPB2


#define B_SET   OB3
#define C_SET   GPB5
#define B_RESET OB2
#define C_RESET GPB4


#define C_SET   OB5
#define D_SET   GPB7
#define C_RESET OB4
#define D_RESET GPB6


#define D_SET   OB7
#define E_SET   GPA0
#define D_RESET OB6
#define E_RESET GPA1


#define E_SET   OA0
#define F_SET   GPA2
#define E_RESET OA1
#define F_RESET GPA3


#define F_SET   OA2
#define G_SET   GPA4
#define F_RESET OA3
#define G_RESET GPA5


#define G_SET   OA4
#define H_SET   GPA6
#define G_RESET OA5
#define H_RESET GPA7


#define H_SET  OA6
boolean state[16];
#define H_RESET OA7


void setup() {
void setup() {


   SerialUSB.begin(115200);
   SerialUSB.begin(115200);
  while (!SerialUSB) {
    delay(100);
  }


   SerialUSB.println("SetupMCP Relais Test ...");
   SerialUSB.println("SetupMCP Relais Test ...");
Line 157: Line 162:
   for (int i = 0; i < 16; i++) {
   for (int i = 0; i < 16; i++) {
     mcp.pinMode(i, OUTPUT);
     mcp.pinMode(i, OUTPUT);
    state[i]=false;
    setMCP(i, false);
   }
   }


  pulseMCP(A_RESET);
//#define D 100
  pulseMCP(B_RESET);
  pulseMCP(C_RESET);
  pulseMCP(D_RESET);
  pulseMCP(E_RESET);
  pulseMCP(F_RESET);
  pulseMCP(G_RESET);
  pulseMCP(H_RESET);




   SerialUSB.println("... done");
   SerialUSB.println("... done");
  digitalWrite(LED, LOW);


   // initial delay
   // initial delay
Line 184: Line 185:


String cmd;
String cmd;
char c[4];


void loop() {
void loop() {
Line 189: Line 194:
   cmd = SerialUSB.readStringUntil('\n');
   cmd = SerialUSB.readStringUntil('\n');


   if (cmd.length() > 0) {
   if (cmd.length() == 2) {
 
     SerialUSB.print("Command: ");
     SerialUSB.print("Command: ");
     SerialUSB.println(cmd);
     SerialUSB.println(cmd);
Line 242: Line 248:


     SerialUSB.println("\n\nWaiting for command...[a-h0-1]");
     SerialUSB.println("\n\nWaiting for command...[a-h0-1]");
  } else if (cmd.length() == 4) {
    SerialUSB.print("Command: ");
    SerialUSB.println(cmd);
    if (cmd == "gpa0") {
      state[GPA0] = !state[GPA0];
      setMCP(GPA0, state[GPA0gpb5]);
    } else
    if (cmd == "gpa1") {
      state[GPA1] = !state[GPA1];
      setMCP(GPA1, state[GPA1]);
    } else
    if (cmd == "gpa2") {
      state[GPA2] = !state[GPA2];
      setMCP(GPA2, state[GPA2]);
    } else
    if (cmd == "gpa3") {
      state[GPA3] = !state[GPA3];
      setMCP(GPA3, state[GPA3]);
    } else
    if (cmd == "gpa4") {
      state[GPA4] = !state[GPA4];
      setMCP(GPA4, state[GPA4]);
    } else
    if (cmd == "gpa5") {
      state[GPA5] = !state[GPA5];
      setMCP(GPA5, state[GPA5]);
    } else
    if (cmd == "gpa6") {
      state[GPA6] = !state[GPA6];
      setMCP(GPA6, state[GPA6]);
    } else
    if (cmd == "gpa7") {
      state[GPA7] = !state[GPA7];
      setMCP(GPA7, state[GPA7]);
    } else
    if (cmd == "gpb0") {
      state[GPB0] = !state[GPB0];
      setMCP(GPB0, state[GPB0]);
    } else
    if (cmd == "gpb1") {
      state[GPB1] = !state[GPB1];
      setMCP(GPB1, state[GPB1]);
    } else
    if (cmd == "gpb2") {
      state[GPB2] = !state[GPB2];
      setMCP(GPB2, state[GPB2]);
    } else
    if (cmd == "gpb3") {
      state[GPB3] = !state[GPB3];
      setMCP(GPB3, state[GPB3]);
    } else
    if (cmd == "gpb4") {
      state[GPB4] = !state[GPB4];
      setMCP(GPB4, state[GPB4]);
    } else
    if (cmd == "gpb5") {
      state[GPB5] = !state[GPB5];
      setMCP(GPB5, state[GPB5]);
    } else
    if (cmd == "gpb6") {
      state[GPB6] = !state[GPB6];
      setMCP(GPB6, state[GPB6]);
    } else
    if (cmd == "gpb7") {
      state[GPB7] = !state[GPB7];
      setMCP(GPB7, state[GPB7]);
    }
   
   }
   }
}


void setMCP(int i, boolean s){
  SerialUSB.print("Set addr #");
  SerialUSB.print(i);
  SerialUSB.print(" to ");
  SerialUSB.println(s);
  mcp.digitalWrite(i, s);
}
}


Line 258: Line 341:
</syntaxhighlight>
</syntaxhighlight>


If there are relais that do not switch, follow these steps:
# Set MCP IO pin one by one and check if voltage (0V vs. 3.3V) can be measured between MCP IC and ULN2803 IC.
# Measure also the voltage on ULN2803 output pin.


If MCP fires 0V (low), ULN should almost show 5V (typically 4.8V) on output. If MCP fires 3.3V (high) the ULN output voltage will go down to almost 0V (low), but typically 0.7V. If itÄs 0.9V, it will work as well. But if voltage just drops to 1..1.5V, the ULN driver IC is bad and needs to be replaced. Make sure you use a genuine one and not a china-copy.


== Links ==
== Links ==


[[Category:Device/Kits]]
[[Category:Device/Kits]]

Latest revision as of 11:55, 20 February 2022

DFF4.1
Developer Alexander Christian
Status Version 1.0 finished
Microcontroller/Board M0dularisM+
KNX connectivity Siemens BCU, Eugen's µBCU


Description

The purpose of this actuator is, to control Roto Rototronic skylight with shutters and/or sun blinds. It has 4 "channels". Each channel internally uses two relays: One for the open-action, and one for the close-action.

Of course you can also control your Roto Rototronic skylight with help of a standard switch-actuator. But then you don't have the possibility to "open the window 75%" or "close the shutter 80%". The firmware for DFF4.1 provides all this neat feature that you know from typical shutter/blinds actuators.

Hardware

This actuator consists of the following REG parts:

I2C address on application board:

A0: 1
A1: 0 
A2: 0

I2C address on frontend board:

A0: 0
A1: 0
A2: 0


Software

User Documentation

Check here for the DFF4.1 User Manual

Developer Documentation

Firmware sourcecode is on github: https://github.com/KONNEKTING/DFF4.1 Follow this guide for updating the firmare from source-code: KONNEKTING USB Firmware Update

Get a DIY kit

You are interested in this actuator? Great! This device is available as a DIY kit.

The kit includes all required parts with pre-soldered SMD parts and pre-flashed controller board.

You only need:

  • soldering iron and solder
  • a screw driver
  • a sharp knife with a fine tip
  • a working KNX installation where you can connect the device to
  • ~2-3hrs to build it according to the build instructions linked on this page
  • a computer: Windows, Linux or MAC that is able to run KONNEKTING Suite plus a KNX IP Interface or an KNX IP Router.
  • for updating the firmware: A Mini USB cable (Not Micro-USB like on your smartphone. Mini USB is a big thicker as Micro USB)

Please write a mail to info@konnekting.de and refer to this page.

Build It

This actuator uses three PCBs, a bunch of SMD components as well as a lot of mechanical parts. As most users are not able to solder SMD, the PCBs are pre-soldered with all SMD components. Due to the big amount of parts, this actuator comes as a DIY kit: You have to solder non-SMD parts yourself and build up the device and finally flash the firmware with help of a USB connection.

Check here for the DFF4.1 Building Instructions

Help

If relays do not work as expected, you can run this test-sketch to be able to switch relais by serial console. Commands follow this syntax (\n = LF/LineFeed/NewLine):

[a-h0-1]\n

f.i. "a0" disables relay A, "f1" enables relay F On startup all relays are disabled. It is recommended to use this test without attached window/shutter, but with am multimeter/continuity-tester to be able to test relay by relay.

#include <Wire.h>
#include <Adafruit_MCP23017.h>

Adafruit_MCP23017 mcp;
#define LED A5
#define EN A0

// MCP23017 Output register<->pin map
#define GPA0 0 // E 1
#define GPA1 1 // E 0 
#define GPA2 2
#define GPA3 3
#define GPA4 4
#define GPA5 5
#define GPA6 6
#define GPA7 7
#define GPB0 8
#define GPB1 9
#define GPB2 10 // B 0
#define GPB3 11 // B 1
#define GPB4 12 // C 0
#define GPB5 13 // C 1
#define GPB6 14 // D 0
#define GPB7 15 // D 1

#define A_SET   GPB1
#define A_RESET GPB0

#define B_SET   GPB3
#define B_RESET GPB2

#define C_SET   GPB5
#define C_RESET GPB4

#define D_SET   GPB7
#define D_RESET GPB6

#define E_SET   GPA0
#define E_RESET GPA1

#define F_SET   GPA2
#define F_RESET GPA3

#define G_SET   GPA4
#define G_RESET GPA5

#define H_SET   GPA6
#define H_RESET GPA7

boolean state[16];

void setup() {


  SerialUSB.begin(115200);
  while (!SerialUSB) {
    delay(100);
  }

  SerialUSB.println("SetupMCP Relais Test ...");

  pinMode(LED, OUTPUT);
  pinMode(EN, OUTPUT);
  digitalWrite(LED, HIGH);
  digitalWrite(EN, HIGH);


  mcp.begin(1);

  for (int i = 0; i < 16; i++) {
    mcp.pinMode(i, OUTPUT);
    state[i]=false;
    setMCP(i, false);
  }

//#define D 100


  SerialUSB.println("... done");
  digitalWrite(LED, LOW);

  // initial delay
  delay(1000);
  SerialUSB.println("Initial delay done.");
  SerialUSB.println("Waiting for command...[a-h0-1]");
}

//84
#define WAIT_TIME 84

//16
#define SET_TIME 16

String cmd;

char c[4];



void loop() {

  cmd = SerialUSB.readStringUntil('\n');

  if (cmd.length() == 2) {

    SerialUSB.print("Command: ");
    SerialUSB.println(cmd);

    if (cmd == "a1") {
      pulseMCP(A_SET);
    } else if (cmd == "a0") {
      pulseMCP(A_RESET);
    }

    else if (cmd == "b1") {
      pulseMCP(B_SET);
    } else if (cmd == "b0") {
      pulseMCP(B_RESET);
    }

    else if (cmd == "c1") {
      pulseMCP(C_SET);
    } else if (cmd == "c0") {
      pulseMCP(C_RESET);
    }

    else if (cmd == "d1") {
      pulseMCP(D_SET);
    } else if (cmd == "d0") {
      pulseMCP(D_RESET);
    }

    else if (cmd == "e1") {
      pulseMCP(E_SET);
    } else if (cmd == "e0") {
      pulseMCP(E_RESET);
    }

    else if (cmd == "f1") {
      pulseMCP(F_SET);
    } else if (cmd == "f0") {
      pulseMCP(F_RESET);
    }

    else if (cmd == "g1") {
      pulseMCP(G_SET);
    } else if (cmd == "g0") {
      pulseMCP(G_RESET);
    }

    else if (cmd == "h1") {
      pulseMCP(H_SET);
    } else if (cmd == "h0") {
      pulseMCP(H_RESET);
    }

    SerialUSB.println("\n\nWaiting for command...[a-h0-1]");

  } else if (cmd.length() == 4) {
    SerialUSB.print("Command: ");
    SerialUSB.println(cmd);

    if (cmd == "gpa0") {
      state[GPA0] = !state[GPA0];
      setMCP(GPA0, state[GPA0gpb5]);
    } else 
    if (cmd == "gpa1") {
      state[GPA1] = !state[GPA1];
      setMCP(GPA1, state[GPA1]);
    } else 
    if (cmd == "gpa2") {
      state[GPA2] = !state[GPA2];
      setMCP(GPA2, state[GPA2]);
    } else 
    if (cmd == "gpa3") {
      state[GPA3] = !state[GPA3];
      setMCP(GPA3, state[GPA3]);
    } else 
    if (cmd == "gpa4") {
      state[GPA4] = !state[GPA4];
      setMCP(GPA4, state[GPA4]);
    } else 
    if (cmd == "gpa5") {
      state[GPA5] = !state[GPA5];
      setMCP(GPA5, state[GPA5]);
    } else 
    if (cmd == "gpa6") {
      state[GPA6] = !state[GPA6];
      setMCP(GPA6, state[GPA6]);
    } else 
    if (cmd == "gpa7") {
      state[GPA7] = !state[GPA7];
      setMCP(GPA7, state[GPA7]);
    } else
    if (cmd == "gpb0") {
      state[GPB0] = !state[GPB0];
      setMCP(GPB0, state[GPB0]);
    } else 
    if (cmd == "gpb1") {
      state[GPB1] = !state[GPB1];
      setMCP(GPB1, state[GPB1]);
    } else 
    if (cmd == "gpb2") {
      state[GPB2] = !state[GPB2];
      setMCP(GPB2, state[GPB2]);
    } else 
    if (cmd == "gpb3") {
      state[GPB3] = !state[GPB3];
      setMCP(GPB3, state[GPB3]);
    } else 
    if (cmd == "gpb4") {
      state[GPB4] = !state[GPB4];
      setMCP(GPB4, state[GPB4]);
    } else 
    if (cmd == "gpb5") {
      state[GPB5] = !state[GPB5];
      setMCP(GPB5, state[GPB5]);
    } else 
    if (cmd == "gpb6") {
      state[GPB6] = !state[GPB6];
      setMCP(GPB6, state[GPB6]);
    } else 
    if (cmd == "gpb7") {
      state[GPB7] = !state[GPB7];
      setMCP(GPB7, state[GPB7]);
    } 
    
  }
}

void setMCP(int i, boolean s){
  SerialUSB.print("Set addr #");
  SerialUSB.print(i);
  SerialUSB.print(" to ");
  SerialUSB.println(s);
  mcp.digitalWrite(i, s);
}

void pulseMCP(int i) {
  SerialUSB.print("Pulse at addr #");
  SerialUSB.print(i);

  mcp.digitalWrite(i, HIGH);
  delay(SET_TIME);
  mcp.digitalWrite(i, LOW);
  delay(WAIT_TIME);
  SerialUSB.println(" *DONE*");
}

If there are relais that do not switch, follow these steps:

  1. Set MCP IO pin one by one and check if voltage (0V vs. 3.3V) can be measured between MCP IC and ULN2803 IC.
  2. Measure also the voltage on ULN2803 output pin.

If MCP fires 0V (low), ULN should almost show 5V (typically 4.8V) on output. If MCP fires 3.3V (high) the ULN output voltage will go down to almost 0V (low), but typically 0.7V. If itÄs 0.9V, it will work as well. But if voltage just drops to 1..1.5V, the ULN driver IC is bad and needs to be replaced. Make sure you use a genuine one and not a china-copy.

Links