Inconsistent Power Scaling with Arduino Control - Page 3

Discuss roast levels and profiles for espresso, equipment for roasting coffee.
false1001
Posts: 279
Joined: 6 years ago

#21: Post by false1001 »

btreichel wrote:Have you taken into account that with zero crossing and firing a pwn to turn on power, that the power is non-linear. AKA 0 to 30 is almost no power, past 70% it also hardly matters.
this is the correct answer. ira is also correct about the cycle time, but that really shouldn't matter since you don't care about matching a temp to a high degree of precision over a long period of time, you just need predictable increases/decreases in heat output.

I would recommend getting a TC4 and wiring up your popper according to this diagram, I had great success with it: https://cpb-us-w2.wpmucdn.com/muse.unio ... le-TC4.png

You can then wire up the arduino to control the angular inputs instead of potentiometers

uwe
Posts: 4
Joined: 4 years ago

#22: Post by uwe »

@ira
I followed your advice and added the line you wrote:

if ( (i % 20) == 0) {
slave.poll( au16data, 16 );
}

Then I could set delay to 24 ms and the MODBUS connection remained perfectly stable. And, as you predicted, with the increased cycle time the power output is linear over the whole range and there is no strong rise when I go above 98%.Perfect!

Thank you very much for your explanations and this code !!!
Uwe

ira
Team HB
Posts: 5497
Joined: 16 years ago

#23: Post by ira »

You're quite welcome. It's really a simple problem, sorry it took so long to get to a working solution.

Ira

marcism (original poster)
Posts: 131
Joined: 11 years ago

#24: Post by marcism (original poster) »

uwe wrote:@ira
I followed your advice and added the line you wrote:

if ( (i % 20) == 0) {
slave.poll( au16data, 16 );
}

Then I could set delay to 24 ms and the MODBUS connection remained perfectly stable. And, as you predicted, with the increased cycle time the power output is linear over the whole range and there is no strong rise when I go above 98%.Perfect!

Thank you very much for your explanations and this code !!!
Uwe
Amazing!! Can you post your whole sketch?

@ira you might've solved so much heartache for so many home roasters.

uwe
Posts: 4
Joined: 4 years ago

#25: Post by uwe »

Here is the code; this works really fantastic now, PID control is also improved. Thank you again,ira!
// this example is public domain. enjoy!
// www.ladyada.net/learn/sensors/thermocouple

#include <max6675.h>
#include <Adafruit_MAX31865.h>
#include <ModbusRtu.h>

// data array for modbus network sharing
uint16_t au16data[16] = {
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1 };
 

/**
 *  Modbus object declaration
 *  u8id : node id = 0 for master, = 1..247 for slave
 *  u8serno : serial port (use 0 for Serial)
 *  u8txenpin : 0 for RS-232 and USB-FTDI 
 *               or any pin number > 1 for RS-485
 */
Modbus slave(1,0,0); // this is slave @1 and RS-232 or USB-FTDI

// Use software SPI: CS, DI, DO, CLK
Adafruit_MAX31865 max = Adafruit_MAX31865(10, 11, 12, 13);
// use hardware SPI, just pass in the CS pin
//Adafruit_MAX31865 max = Adafruit_MAX31865(10);

// The value of the Rref resistor. Use 430.0 for PT100 and 4300.0 for PT1000
#define RREF      430.0
// The 'nominal' 0-degrees-C resistance of the sensor
// 100.0 for PT100, 1000.0 for PT1000
#define RNOMINAL  100.0


int thermoDO = 2;
int thermoCS = 3;
int thermoCLK = 4;


MAX6675 thermocoupleET(thermoCLK, thermoCS, thermoDO);

float BT = -1.00;
float ET = -1.00;

int vccPin = 5;
int gndPin = 6;
  

int led = 9;  
  
void setup() {
  slave.begin( 19200, SERIAL_8E1 ); // 19200 baud, 8-bits, even, 1-bit stop
  // use Arduino pins 
  pinMode(vccPin, OUTPUT); digitalWrite(vccPin, HIGH);
  pinMode(gndPin, OUTPUT); digitalWrite(gndPin, LOW);
  pinMode(led, OUTPUT);
  max.begin(MAX31865_4WIRE);  // set to 2WIRE or 4WIRE as necessary
 delay(500);
  
}

void loop() {
  // basic readout test, just print the current temp
  
   //Serial.print("C = "); 
   ET = thermocoupleET.readCelsius();
   BT = max.temperature(RNOMINAL, RREF);
   
   au16data[2] = ((uint16_t) (BT*100));
   au16data[3] = ((uint16_t) (ET*100));
   slave.poll( au16data, 16 );

   for(int i=1; i<=99; i++) {
    if(i<=au16data[4])
      digitalWrite(led, HIGH);
    else
      digitalWrite(led, LOW);
    if ( (i % 20) == 0) {
    slave.poll( au16data, 16 );
}
    delay(24);
   }
   
}

marcism (original poster)
Posts: 131
Joined: 11 years ago

#26: Post by marcism (original poster) »

It worked.



I had to raise my delay quite a bit actually to lower the jump. So much so that I got it all the way to 40! Seems stable and now the bump is negligible as seen in the picture. You can see the difference with one of my old profiles in the background.

@ira and everyone else, you guys are great! Thanks for the help.

Here's my sketch for those wondering:
// this example is public domain. enjoy!
// www.ladyada.net/learn/sensors/thermocouple

#include <max6675.h>
#include <ModbusRtu.h>

// data array for modbus network sharing
uint16_t au16data[16] = {
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1 };

/**
 *  Modbus object declaration
 *  u8id : node id = 0 for master, = 1..247 for slave
 *  u8serno : serial port (use 0 for Serial)
 *  u8txenpin : 0 for RS-232 and USB-FTDI 
 *               or any pin number > 1 for RS-485
 */
Modbus slave(1,0,0); // this is slave @1 and RS-232 or USB-FTDI



//Thermocouple 1
int thermoDO = 2;
int thermoCS = 3;
int thermoCLK = 4;

//Thermocouple 2
int thermoDO2 = 8; // Add a 2 to each int from first Thermocouple. Ex(ThermoDO to ThermoDO2).
int thermoCS2 = 9; // Change pins to the ones you use for your board. Can be any digital pins.
int thermoCLK2 = 7;

MAX6675 thermocouple2(thermoCLK, thermoCS, thermoDO);

MAX6675 thermocouple(thermoCLK2, thermoCS2, thermoDO2); //Thermocouple 2
  
int led = 5;  
  
void setup() {
  slave.begin( 19200 ); // 19200 baud, 8-bits, none, 1-bit stop
  // use Arduino pins 
  pinMode(led, OUTPUT);
 delay(500);
  
}

void loop() {
  // basic readout test, just print the current temp
  
   //Serial.print("C = "); 
   
   au16data[2] = (uint16_t) (thermocouple.readCelsius()*100); 
   
   au16data[3] = (uint16_t) (thermocouple2.readCelsius()*100);
   
   slave.poll( au16data, 16 );

   for(int i=1; i<=99; i++) {
    if(i<=au16data[4])
       digitalWrite(led, HIGH);
      else
        digitalWrite(led, LOW);
      if ( (i % 20) == 0) {
        slave.poll( au16data, 16 );
      }
    delay(40);
   }
   
}

User avatar
CarefreeBuzzBuzz
Posts: 3863
Joined: 7 years ago

#27: Post by CarefreeBuzzBuzz »

If this is useful for the Artisan community at large I will be happy to post it on the Quick Start Guide if someone does a detailed summary post. Thanks.
Artisan.Plus User-
Artisan Quick Start Guide
http://bit.ly/ArtisanQuickStart

marcism (original poster)
Posts: 131
Joined: 11 years ago

#28: Post by marcism (original poster) replying to CarefreeBuzzBuzz »

This would be great, but I actually don't think I fully understood enough of what was going on with this fix to write out a proper summary.

One thing that I still get a bit of is temperature reading instability from the MAX6675's. Is there a way to force both thermocouples to read at 250ms intervals (their recommended latency), so that the readings stabilise a bit?

ira
Team HB
Posts: 5497
Joined: 16 years ago

#29: Post by ira »

I don't understand what you're asking here. It's hard to get a thermocouple to read clean because they are so sensitive to electrical noise. I use this to help filter that noise in trade for a slight delay in response time.

When you get a temperature reading you do this with it.
unsigned char FILTER_BITS = 2;  Try numbers between 1 and 4
unsigned long RollingTemp = 100; Must be global or static

unsigned int tempTemp
tempTemp = RollingTemp/FILTER_BITS
RollingTemp += (NewTemperature - tempTemp);
And when you want to know the temperature, you read:
  (RollingTemp / FILTER_BITS)
Ira

uwe
Posts: 4
Joined: 4 years ago

#30: Post by uwe »

regarding temperature reading: here's an excelent article from Marko : https://artisan-roasterscope.blogspot.c ... noise.html
A thermocouple with MAX 6675 is noisy. RTDs are much better. For that reason, I use a PT100 for measuring BT.
I attached a picture where you can see the ditterence; ET is measured viaTC, BT by a Pt100.