Some time ago I move to a new house and bought a new kitchen, an induction type. The electronic panel was useful to eliminate the possibility to end up eating a burned food, but the oven still was classic design. A mechanical thermostat and mechanical switch to activate heater elements. I didn't bother with that until one day the oven stop working, since the kitchen was on warranty period, the technician came and I found with him that the mechanical switch was so bad in design that it melt. After I replacement I was not convinced since the same element model was used as replacement. Two weeks later same problem, but the kitchen was not anymore under warranty period.
I was struggling long time to do something since I was not willing to put a similar mechanical element, neither I was motivated to implement something by myself since I imagine the painful design using potentiometers for example.
The new 3D magnetic sensors from Infineon was enough motivating to create a new product to solve the problem.
The ProblemIf you think about it, this is not the kind of hacking hardware you want to do that sometimes work and sometimes not. You don't want to receive a call from grandma with the lasagna ready for the oven because it just don't work, don't even mention it stop working at the middle of the cooking. Although people tend to underestimate a design for a product like this, this is one of those products you need to work reliable, in short an embedded product.
The SolutionThe product have to do a few things to replace conventional thermostat + mechanical switch.
- Convert Knob angle position to desired setting.
- Act upon Knob current position or state.
The first point above involves several tasks. A 3D sensor is used in conjunction with a mechanical design that has a magnet, this magnet produces the field that is sensed with TLE493D device in order to determine the angle of the Knob. The angle is then converted to some human readable unit such as temperature of heat element setting.
In short the first point will handle the Input from user, that is temperature and heat element switch position. A knob will be dedicated to temperature readings and another to heat element position readings.
The second point above close the loop, for this an external device to handle the large currents from heat elements will be used, this are commonly found SSR devices. Of course we need the feedback, in this case a thermocouple to read actual temperature inside the oven.
Kitchen Knob Mechanical DesignThe 3D MS2Go board from Infineon is a good starting point to explore the sensor, but in this case a product design is the goal. In order to do this I have taken apart my kitchen to found how I will fix the smart knob inside.
The mechanical damaged switch was the starting point. it has two holes in front for screwing into a plate, so the Knob pin slide out of the hole as you can see on the picture. Here is a closed look that shows the damage and the two holes.
I decide to use a 1/2in by 1/2 in neodymium magnet, perhaps it's somehow overestimated in size but I was not really sure.
After some time designing the mechanical part, a lot of redesign and some wasted PLA.
I came out with my best design for this. Is easy to assembly, actually only the knob pin need some crazy glue to fix to the magnet holder.
Thou I am pretty happy with it, it might have some minor improvements, but the design will be unchanged by those.
On one of the iterations of the design I was trying to use the screws of the original part, then I notice the screws interfere with the magnet making it difficult to rotate without bending towards one or the other side. One of the improvements will be to use similar design with little magnet. But since this neodymium magnet are very strong, I doubt the conflict will end with that. So I decide to use nylon screw and threads, thou I have them in the "screw box" that my wife always stare at like "are you still keeping those...", not sure how much will cost or how difficult are them to find.
The magnet goes into a piece that holds it securely. This piece has a sleeve that tied to the knob part allow it rotation. In order to prevent the mechanism from getting out the cylinder is bigger enough to slide in the case wall which has a small groove. Taking into consideration the knob pin print alone, four pieces conform the mechanism. There is no need to close anything, the two nylon screws will fix it to the kitchen fixture. The following picture show the hidden features explained above.
One missing features of this design is the push button ability. Thou it might be required, the original kitchen does not include it.
The electronics of this project was also a no breadboard design, thou I did a single layer PCB to test the idea, but also because it was made locally before the original deadline. It serves to test the idea but since contest deadline was extended significantly I decide to do a more elaborate design later on.
Since first prototype was for tests on my benchtop I didn't populate the power supply components.
Notice that the magnetic sensor was on bottom layer centered where the magnet should be. The bottom 5 pin header single row header shown in the Top below the XMC board is for the external MAX6675 breakout board.
The blue terminal blocks on the PCB of early prototype are for transistor output to handle external SSR, since an oven can consume high power which means high currents, an external SSR need to be used. The SSR fits perfectly below the kitchen glass top such as
The features and improvements done for the second prototype include.
- XMC1100 IC can be directly placed for last embedded application.
- Thermocouple circuit for max31856 IC.
- Low Power SSR component. (2A max)
As you can see an XMC1100 device IC can be soldered directly on the board. The 8 pin double row header has SWD/JTAG interfce to program he IC as well as debug FTDI pins, resembling the original XMC board but in this case external JTAG is needed.
Thou copper is magnetic weak material, I leaved a copper free window below the sensor TLE493D on Bottom layer, this helps in assembly correctly on right place.
I haven't had the time to test a board with the XMC1100 device instead of the 3D MS2Go board, it might require some time and I am not sure whether or not a segger JTAG can flash an image, thou it should be possible.
Notice I partially populate the DEBUG header and wire wrap the board Serial port since I haven't exposed the XMC board FTDI pins for serial debugging without the USB cable. Also notice that even if I cut the board sensor part out, it still does not fit on place, this is because It was designed for the XMC 2Go board.
The reason the XMC 2Go board was not used will be discussed later, but basically I2C was not working on that board.
The power supply design uses a power transformer from Remco that is IEC/EN60950-1 certified, other protection devices such SMD Fuse and Varistor are placed for fulfill protection. Also EMC X7R capacitor have been included as well.
The Power supply produces 5V. This power rail is certainly needed to handle some external SSR models. Some designs such as the one I have used for my Reflow Oven, uses 3.3V, which might work with some SSR models, but not for mine here. For this reason I have to include a 3.3V regulator as well.
I haven't tested the MAX31856 circuit for two reasons. Oneis that I do not have the IC at hand. Second, since I am still developing the project, I cannot use SPI for it while using Serial for debug and Wire for TLE493D. With MAX6675, the library I use is implemented using bit bang rather than the SPI peripheral.
The assembled device looks like this.
Software DesignThis was the tough part of the project, because available arduino library here seems to have some issues, not only reported by me but from other community folks.
The problem is sometimes related to I2C peripheral thou it's not confirmed by developers. The certain thing is that I spend more time than the one I was expecting to make it work in reliable way. Remember grandma will give a s' when the oven don't work because of you.
TLE493D FirmwareThere are different versions of magnetic sensors from Infineon out there. The 3D MS2Go kit seems to come with TLE493DA2B6. I have purchased additional samples but of TLE493DW2B6, one of the obvious differences is the I2C address.
The good thing is that the library works with both, just have to use different primitives. I end up using the TLE493DW2B6 for my custom board.
After a lot of debugging the I2C communications and diving into the library code, a long discussion here and here, I could end up with some code that is reliable so far.
The sensor initialization begin function was change to fix values and for some reason not determined yet I have to call the first I2C write twice.
void Tle493d::begin(TwoWire &bus, TypeAddress_e slaveAddress, bool reset, uint8_t oneByteRead)
{
//TURN ON THE SENSOR
// pinMode(LED2, OUTPUT);
// digitalWrite(LED2, HIGH);
initInterface(&mInterface, &bus, slaveAddress, tle493d::resetValues);
// mInterface.bus->begin();
// mInterface.bus->setClock(100000);
// if(reset == true)
// {
// resetSensor();
// }
//1-byte protocol -> PR = 1
setRegBits(tle493d::PR, oneByteRead);
//correct reset values for other product types
switch(mProductType)
{
case TLE493D_A1:
setRegBits(tle493d::IICadr, 0x01);
setRegBits(tle493d::ID, 0x01);
break;
case TLE493D_A2:
setRegBits(tle493d::IICadr, 0x10);
setRegBits(tle493d::ID, 0x10);
break;
case TLE493D_A3:
setRegBits(tle493d::IICadr, 0x11);
setRegBits(tle493d::ID, 0x11);
break;
default: break;
}
// default: master controlled mode
setAccessMode(mMode);
calcParity(tle493d::CP);
calcParity(tle493d::FP);
mInterface.bus->beginTransmission(slaveAddress);
mInterface.bus->write(0x10);
mInterface.bus->write(0b01010001);
mInterface.bus->endTransmission();
delayMicroseconds(15);
//write out the configuration register
mInterface.bus->beginTransmission(slaveAddress);
mInterface.bus->write(0x10);
mInterface.bus->write(0b01010001);
mInterface.bus->endTransmission();
//tle493d::writeOut(&mInterface, 0x10);
delayMicroseconds(5);
//write out MOD1 register
mInterface.bus->beginTransmission(slaveAddress);
mInterface.bus->write(0x11);
mInterface.bus->write(0b00110001);
mInterface.bus->endTransmission();
delay(TLE493D_STARTUPDELAY);
}
Notice I end up commenting the Wire.begin and setClock functions here, which I call from the Arduino IDE main code.
The LEd on command is neccesarry but I commented from the library since I was using ATSAMD1 also during my tests. The reason is necessary is because I am still using the 3D MS2Go board which has the pull ups tied to the LED pin output,
fail to write High level and I2C waveform will look like this
I also rewrite the reset function, partially taken from the example code here. The function seems to work, or at least don't hand the sensor IC as reported and commented in the original library function. I can restart the code by reprogramming the board under arduino IDE and the sensor continue to work.
void resetSensor() {
// 0xFF
i2c_Start();
for (int i = 0; i < 8; ++i) {
i2c_Bit(0x1);
}
i2c_Stop();
delayMicroseconds(20);
// 0xFF
i2c_Start();
for (int i = 0; i < 8; ++i) {
i2c_Bit(0x1);
}
i2c_Stop();
delayMicroseconds(20);
// 0x00
i2c_Start();
pinMode(PIN_SDA, OUTPUT);
for (int i = 0; i < 8; ++i) {
i2c_Bit(0x0);
}
i2c_Stop();
delayMicroseconds(20);
// 0x00
i2c_Start();
pinMode(PIN_SDA, OUTPUT);
for (int i = 0; i < 8; ++i) {
i2c_Bit(0x0);
}
i2c_Stop();
delayMicroseconds(30);
}
I problem with this code is reported here. The problem seems to be thenature of I/O state during Input and Output transition for XMC1100 device. Normally you have a latch register but in this case it seems the latch is missing. I am not sure since I haven't study the XMC1100 details.
The initialization looks like normal way to coding it, such as
Wire.begin();
Wire.setClock(10000);
#ifdef DEBUG
Serial.begin(9600);
while (!Serial);
#endif
delay(500);
Tle493dMagnetic3DSensor.begin();
Wire.end();
Notice I am making end on Wire. This is because I am doing begin every time I need a new sample such as
Wire.begin();
Wire.setClock(100000);
delay(10);
int err = Tle493dMagnetic3DSensor.updateData();
err = Tle493dMagnetic3DSensor.updateData();
If you fail to call updateData twice here, sensor data will be null. Also notice the begin and setClock here.
This might not be the best way to handle the sensor, but since this application is not really low power application in mind, at least at this stage, and I have found that 5 samples per seconds is perfectly ok to handle user changes to the Knob, is not a problem here.
If err variable is not TLE493D_NO_ERROR, the I can get the X and Y values to convertto angle of the Knob by doing
if (err != TLE493D_NO_ERROR) {
#ifdef DEBUG
Serial.print("Error on Update: ");
Serial.println(err);
#endif
delay(1000);
// resetFunc();
} else {
angle = map(atan2(Tle493dMagnetic3DSensor.getY(), Tle493dMagnetic3DSensor.getX()) * (180 / M_PI), -180.00, 180.00, 0.00, 360.00);
if (abs(prevAngle - angle) >= 5.0) {
prevAngle = angle;
trigChg = true;
#ifdef DEBUG
Serial.print("angle = ");
Serial.println(angle);
#endif
}
}
I am using a variable prevAngle that holds the last angle value acquired which is valid for further processing, more on that in a moment. The trigChg variable serve to trigger the section of code that checks for angle value to take actions such SSR output activating/deactivating.
There is a problem I noticed when trying to convert angle to input from user. The problem is that is almost impossible to calibrate the zero angle given by the neodymium magnet with the actual zero in user units, for example the OFF state., or even any value at all. And so a calibration seems to be required for each device. This is not big issue as I solved by software in a very compact way.
The trigger variable when true initiate the conversion. I have only work on the Knob for temperature sensing which is the most complicated, since there is a range where you rotate the knob and expect the device to interpret every reading as a setpoint temperature.
There are two scenarios depending on where the real 360 grads from sensor reading is located. One case is when it is located between the minimum and maximum value when the knob is rotated clockwise. Other case is when is located between the maximum and minimum value (gearing the knob clockwise when you pass the max point such as the OFF point).
The code that handle the angle to setpoint conversion is as follows.
if (trigChg) {
trigChg = false;
// angle should increment when knob turns clockwise
if (calPoints == calComplete) {
if (highAngle > lowAngle) {
if ((prevAngle > highAngle) || (prevAngle < lowAngle)) {
#ifdef DEBUG
Serial.println("Knob is in OFF region");
delay(1000);
#endif
ovenStatus = OVEN_STATUS_OFF;
} else {
spChange = true;
// this is the case when for example High=270, Low = 60 , range = 210
float m = (spMax - spMin) / (highAngle - lowAngle);
newT = prevAngle * m + spMin;
#ifdef DEBUG
Serial.print("Setpoint = ");
Serial.println(newT);
#endif
}
} else {
if ((prevAngle > highAngle) && (prevAngle < lowAngle)) {
#ifdef DEBUG
Serial.println("Knob is in OFF region");
delay(500); // reduce debugging messages
#endif
ovenStatus = OVEN_STATUS_OFF;
} else {
spChange = true;
float range = highAngle + (360 - lowAngle);
float m = (spMax - spMin) / range;
float Alpha;
if (prevAngle > lowAngle) {
Alpha = prevAngle - lowAngle;
} else {
Alpha = (360 - lowAngle) + prevAngle;
}
newT = Alpha * m + spMin;
#ifdef DEBUG
Serial.print("Setpoint = ");
Serial.println(newT);
#endif
}
}
}
}
Any of the above case taken by the execution flow will yield a new value of setpoint in newT variable. Also a variable spChange becomes true in this case. The linear equation is calculated based on minimum value and slope, using max temperature and minimum temperature hardwired in code, this is because most commercial home oven are made with the dial from 50 Celsius to 250 Celsius, but you can change those values after all.
I am using the well known library for PID controller from Brett Beauregard, but I have taken the implementation of the aforementioned reflow oven found here.
The initialization is done every time the dial goes from OFF state to ON state, such as
if(spChange){
spChange = false;
if(ovenStatus == OVEN_STATUS_OFF){
ovenStatus = OVEN_STATUS_ON;
windowStartTime = millis();
// Tell the PID to range between 0 and the full window size
reflowOvenPID.SetOutputLimits(0, windowSize);
reflowOvenPID.SetSampleTime(PID_SAMPLE_TIME);
// Turn the PID on
reflowOvenPID.SetMode(AUTOMATIC);
}
setpoint = newT;
}
Before going forward on the PID, let's discuss the calibration process. Since the knob firmware needs to detect minimum and maximum angles that correspond to temperatures values min and max, a calibration need to be performed. The Serial port is used for this. A simple command of ascii letter is implemented. The idea is to send a character that upon received, a variable is set to a specific value.
if (Serial.available() > 0) {
char incomingByte = Serial.read();
switch (incomingByte) {
case 'z':
if(calPoints != 0x6){
Serial.println("Zero should be the last calibration - Avoid Turn On during calibration");
break;
}
zeroAngle = angle;
Serial.println("Calibrating Zero Position, angle = ");
Serial.println(zeroAngle);
calPoints |= 0x01;
break;
case 'l':
lowAngle = angle;
Serial.println("Calibrating Min Value Position, angle = ");
Serial.println(lowAngle);
calPoints |= 0x02;
break;
case 'h':
highAngle = angle;
Serial.println("Calibrating Max Value Position, angle = ");
Serial.println(highAngle);
calPoints |= 0x04;
break;
case '1':
if (calPoints != calComplete) { // If calibrartion is not done, we can manually change SSR
Serial.println("Toggle SSR 1");
SSR1 ^= 1;
digitalWrite(SSR1_IN, SSR1);
}else{
Serial.println("SSR manual change not allowed");
}
break;
case '2':
if (calPoints != calComplete) { // If calibrartion is not done, we can manually change SSR
Serial.println("Toggle SSR 2");
SSR2 ^= 1;
digitalWrite(SSR2_IN, SSR2);
}else{
Serial.println("SSR manual change not allowed");
}
break;
default:
break;
}
}
In order to avoid the system to try start the PID controller on non calibrated parameters, a variable keep track of calibration state and is checked in different parts of the code, for example the minimum calibration need to set the minimum, the maximum and the OFF positions.
For example, to check calibration
if (calPoints == calComplete) { // proceed only if calibrationwas done
Another aspect is that the last calibration needs to be the OFF state. This is to ensure that the controller will start in the OFF position.
The command line also allow to Turn On/Off the SSR manually when the calibration is not completed.
The PID control loop is
if (calPoints == calComplete) { // proceed only if calibrationwas done
if (ovenStatus == OVEN_STATUS_ON)
{
now = millis();
reflowOvenPID.Compute();
if ((now - windowStartTime) > windowSize)
{
// Time to shift the Relay Window
windowStartTime += windowSize;
}
if (output > (now - windowStartTime))
digitalWrite(SSR1_IN, HIGH);
else
digitalWrite(SSR1_IN, LOW);
}
// Reflow oven process is off, ensure oven is off
else
{
digitalWrite(SSR1_IN, LOW);
}
}
The temperature from the thermocouple is read every cycle after certain period defined by SENSOR_SAMPLING_TIME
if ((millis() - nextRead) > SENSOR_SAMPLING_TIME) {
nextRead = millis();
temperature = temp.read_temp();
if (temperature < 0) {
ovenStatus = OVEN_STATUS_OFF;
// If there is an error with the TC, temperature will be < 0
#ifdef DEBUG
Serial.print("Thermocouple Error on CS");
Serial.println( temperature );
#endif
} else {
input = temperature;
#ifdef DEBUG
if (ovenStatus == OVEN_STATUS_ON) {
printDelay--;
if(!printDelay){
printDelay = 5;
Serial.print("Current Temperature: ");
Serial.println( input );
Serial.print("Current Setpoint: ");
Serial.println( setpoint );
}
}
#endif
}
}
The Max6675 library only need to be defined such
MAX6675 temp(thermoCS, thermoDO, thermoCLK, 1); // 1 means Celsius
Here I found that the XMC1100 arduino core has some issue when the MISO pin is configured as input, thou I can see the signal on my scope, it always read 0. I have raise an issue here, meantime the workaround was to tie another GPIO configured as INPUT to the MISO pin (in order to not break traces on the PCB).
During development I gather the following console output that shows how a calibration is done.
A picture of the system during tests using my reflow oven is shown below.
To demonstrate the device under work with my reflow ovena couple of short videos are better than a 1000 words.
First the device calibration looks like this on the console, the calibration is not shown on the video since I have to move to PC to rite the letter such as "l" for minimum temperature after setting the knob.
With the knob in OFF position I will put it somewhere, the actual value is 134 Celsius as shown in the last part of the above log. The device under work is shown in the following video.
After reaching the setpoint, the knob is moved again to another position.
ConclusionsThis project shows that is possible to build a reliable smart knob for cooking appliances such an oven based on magnetic sensor TLE493D from Infineon and their XMC1100 device using Arduino libraries.
Happy cooking!
Comments