Getting Artisan to talk to Arduino

Discuss roast levels and profiles for espresso, equipment for roasting coffee.
greensloth

#1: Post by greensloth » Apr 14, 2019, 8:51 am

Hi All,

This is my fist post but I've frequented the site off and on for a few years now. I've been homeroasting since around 2011 progressing from a popper to my current setup, the Behmor 1600+. I'm looking to log roasts using Artisan. My data collection hardware is:

MacBook Air (late 2018), OSX Mohave 10.14.4
Arduino Uno
Max 6675
K-type thermocouple

I've been able to log with this hardware using the RoastLogger-Max6675 sketch posted on the Roastlogger site: http://roastlogger.co.uk/coffee/roastlo ... nload.html

I'd really like to use Artisan as it has some features I prefer over Roastlogger. But, I'm having a heck of a time getting any meaningful data into Artisan. I'm not a coder so I've tried several solutions that others have found, to no avail.

I'm currently working with the software setup described in this post: Artisan, Arduino and thermocouple woes.
I made a couple changes to the python script posted there to address exceptions. One was to add the "shebang" line at the beginning. The other was to make the script executable. After those changes, I can run in Artisan without exception messages. Here's what I have now.

Python script:
#!/usr/bin/env python3
import serial
arduino = serial.Serial("/dev/cu.usbmodem14201", 9600)
datas = arduino.readline()
output = datas.decode('utf8')
print (output)
arduino.close()
The Arduino sketch is modified to match my hardware setup:
// this example is public domain. enjoy!
// www.ladyada.net/learn/sensors/thermocouple

#include "max6675.h"

int thermoDO = 6;
int thermoCS = 5;
int thermoCLK = 4;

MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
int vccPin = 3;
int gndPin = 2;

void setup() {
  Serial.begin(9600);
  // use Arduino pins 
  pinMode(vccPin, OUTPUT); digitalWrite(vccPin, HIGH);
  pinMode(gndPin, OUTPUT); digitalWrite(gndPin, LOW);
  
  // Serial.println("MAX6675 test");
  // wait for MAX chip to stabilize
  delay(500);
}

void loop() {
  // basic readout test, just print the current temp
  
   // Serial.print("C = "); 
   // Serial.println(thermocouple.readCelsius());
   // Serial.print("F = ");
   Serial.println(thermocouple.readFahrenheit());
 
   delay(1000);
}

This code works in the Python IDE as shown in the output below:
Image


Artisan Device Assignment:
Image


The Artisan main screen shows the message below. The Port Configuration screen doesn't show any available ports.:
Image


When the scope is turned on, I see "callprogram() received: @line 37497" and no temperature data is displayed:
Image



It seems like Artisan is trying to run the script but isn't communicating with Arduino. I will greatly appreciate any help from the gurus on this site.

gullygossner

#2: Post by gullygossner » Apr 14, 2019, 6:53 pm

I ran mine using the modbus protocol under config>device>meter
Image

Then setup the arduino via the config>port>modbus as follows (note that comm port /dev/tty.usbmodem14101 didn't show up in the drop down, I had to use a terminal command to figure out my comm port and manually enter it)
Image

I used the following sketch pulled from https://medium.com/@lukasgrasse/how-to- ... a3334fd7d5 and modified to work with my max31855. It was originally written to work with the max 6675. I just commented those lines out so it wouldn't take much for you to get it working with your max6675. There is some erroneous code as it was meant to control a SSR for heating. You could comment out or delete those lines if you wanted.
// this example is public domain. enjoy!
// www.ladyada.net/learn/sensors/thermocouple

//#include <max6675.h>
#include <ModbusRtu.h>
#include <Adafruit_MAX31855.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; // this is slave @1 and RS-232 or USB-FTDI




int thermoDO = 10;
int thermoCS = 12;
int thermoCLK = 13;

Adafruit_MAX31855 thermocouple(thermoCLK, thermoCS, thermoDO);
  

int ssr = 5;  
  
void setup() {
  //pinMode(vccPin, OUTPUT); digitalWrite(vccPin, HIGH);
  //pinMode(gndPin, OUTPUT); digitalWrite(gndPin, LOW);
  pinMode(ssr, OUTPUT);
  slave = Modbus(1,0,0);
  slave.begin( 19200 ); // 19200 baud, 8-bits, even, 1-bit stop
  // use Arduino pins 
 delay(500);
  
}

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

   for(int i=1; i<=99; i++) {
    if(i<=au16data[4])
      digitalWrite(ssr, HIGH);
    else
      digitalWrite(ssr, LOW);
    
    delay(5);
   }
   
}

greensloth

#3: Post by greensloth » Apr 15, 2019, 6:44 am

Thanks. The MODBUS setup shown in the Medium article is actually the first one I tried. It was giving me some sort of error that I don't recall. I'll try it again if the Python route comes to a dead end.

gullygossner

#4: Post by gullygossner » Apr 15, 2019, 7:57 am

The original code from the medium post errored for me as well. The posted code is fixed.

greensloth

#5: Post by greensloth » Apr 20, 2019, 8:38 pm

I gave up on the Python script and tried out the Modbus setup. It works. Thanks gullygossner!

I had to tweek a few things for my setup. It wasn't working at first because of the Artisan Device Assignment. I had Curves and LCDs both set to ET only. Apparently Artisan defaults to BT when there is only one input. After correcting this I could log data.

I noticed an error in the Arduino code that caused the temperature to show only integer values. An additional set of parenthesis took care of that. There was a -1 in the line that defines the data array. This caused a warning when compiling the code but didn't seem to affect function. After removing the negative sign, it compiles without errors.

I cleaned up the code a bit and added some comments. The code I'm running is shown below. I'm not running any heater control so those lines are commented out. Hopefully this version will help some other newbies get things up and running.
/*
 * This sketch programs Ardunio to communicate with Artisan using MODBUS protocol and 
 * an inexpensive thermocouple amplifier.
 * 
 * Hardware: 
 *  Arduino UNO
 *  Thermocouple amplifier (MAX6675 or MAX31855)
 *  K-type thermocouple
 *  
 * Libraries needed:
 *  https://github.com/adafruit/Adafruit-MAX31855-library or;
 *  https://github.com/adafruit/MAX6675-library and;
 *  https://github.com/smarmengol/Modbus-Master-Slave-for-Arduino
 */
 
#include <max6675.h>
// #include <Adafruit_MAX31855.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 slave;

// declare variables for Arduino pins connected to the MAX data pins:
int thermoDO = 6;
int thermoCS = 5;
int thermoCLK = 4;

// declare variables for Arduino pins to power MAX:
int vccPin = 3;
int gndPin = 2;

// use the line below that applies
MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
// Adafruit_MAX31855 thermocouple(thermoCLK, thermoCS, thermoDO);

// declare variable for Arduino pin connected to solid state relay (SSR)
// int ssr = 5;  
  
void setup() {
  // configure the pins to power MAX and SSR
  pinMode(vccPin, OUTPUT); digitalWrite(vccPin, HIGH);
  pinMode(gndPin, OUTPUT); digitalWrite(gndPin, LOW);
  // pinMode(ssr, OUTPUT);
  
  slave = Modbus(1,0,0); // MODBUS object declaration: (1 = slave #1, 0 = RS232, 0 = RS232)
  slave.begin( 19200 ); // 19200 baud, 8-bits, none, 1-bit stop
   
  delay(500);
  
}

void loop() {
  
   au16data[2] = ((uint16_t) (thermocouple.readFahrenheit()*10));
   // au16data[2] = ((uint16_t) (thermocouple.readCelsius()*10));
   
   slave.poll( au16data, 16 );

   // heater control loop:
   // for(int i=1; i<=99; i++) {
    // if(i<=au16data[4])
      // digitalWrite(ssr, HIGH);
    // else
      // digitalWrite(ssr, LOW);
   // delay(5);
   // }

   // add delay if commenting out heater control loop
   delay(200);
}

FilePhil

#6: Post by FilePhil » May 03, 2019, 2:22 pm

I have wrote a small example how to send data to Artisan using the TC4 protocol.
It's straight forward and easy to extend.

https://github.com/FilePhil/TC4-Emulator

jpworks76

#7: Post by jpworks76 » May 03, 2019, 9:07 pm

I have been trying to get a Arduino UNO to connect with Artisan. I have had no luck. I was able to get Arduino working with ET/BT thermocouplers and LCDs. I am using set up on a 1kg drum roaster. All I want is to have displays show temps and send needed info to log with Artisan. No plans to control burner. I would could settle for the LCDs and just Arduino sending needed info to Artisan to log. I have no previous experience with programming/coding. Any help would be greatly appreciated.

MAX6675

LCDs TM1637

oldfieldcycles

#8: Post by oldfieldcycles » May 16, 2019, 4:02 pm

i am using the sketch from greensloth and i am getting a modbus communication error, i know my sketch works and my temp sensors are reading because i can output temps in the arduino monitor. i have double checked all the settings in both artisan and my COM settings on my computer any suggestions

oldfieldcycles

#9: Post by oldfieldcycles » May 22, 2019, 1:00 pm

just in case anyone is still trying to get this working with 2 temperature sensors, i spent the last week messing with getting something to work, i modified the code by Lucas and added code to also hook up 2 temperature displays directly to the arduino board. the vcc and gnd pins are all hashed out because the arduino i am using does not have enough pins for the boards to have their own pins so i combined all of the VCC pins to the 5v output pin and the grounds to one ground socket on the arduino. in artisan the settings for the modbus is the same as in previous posts but add in input 2 slave as 1 and register as 3.

// this example is public domain. enjoy!
// www.ladyada.net/learn/sensors/thermocouple
/* this code is a mixture of code by Lukas Grasse and chase from chase'sWKshop youtube channel.
* Written by Ahmad Nejrabi for Robojax Video
* Date: Dec 09, 2017, in Ajax, Ontario, Canada
* Permission granted to share this code given that this
* note is kept with the code.
* Disclaimer: this code is "AS IS" and for educational purpose only.
*
/*Thanks to Robojax for the help with the code. Check out his videos on
*youtube and website Robojax.com*/
/*You can add as many displays by following the directions in the comments
*edited by Chase Weatherford Youtube Channel Chase'sWKshop*/
/*Download source code if want here, http://robojax.com/learn/arduino/?vid=r ... 675-thermo */

//Using Mega2560 Arduino board
//2 Max6675 Thermocouples
//2 TM1637 Digital Displays

#include "max6675.h" //Max6675 thermocouple library include.
#include <Arduino.h>
#include <ModbusRtu.h>
#include <TM1637Display.h> //TM1637 display library include.

// 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; //First code you get from Max6675 library
int thermoCS = 3;
int thermoCLK = 4;

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


// Display 1 connection pins
// (Digital Pins)
int CLK = 8; //CLK and DIO pins numbers for Digital Display.
int DIO = 9;

// Display 2 connection pins
// (Digital Pins)
#define CLK2 10 //Copied contents of Display one and Changed CLK to CLK2 and
#define DIO2 11 //DIO to DIO2.

// The amount of time (in milliseconds) between tests
#define TEST_DELAY 2000

//display 1 setting TM1637Display from display to display1(CLK, DIO)
TM1637Display display1(CLK, DIO);

//display 2 copied contents of above code and changed display1 to display2, CLK to CLK2 and DIO to DIO2
TM1637Display display2(CLK2, DIO2);


MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO); //Thermocouple 1
// int vccPin = 5; //Defining ThermoCLK, CS and DO to thermocouple
//int gndPin = 6; //also set vcc and gnd to pins 3 and 2 can change to other digital pins.

MAX6675 thermocouple2(thermoCLK2, thermoCS2, thermoDO2); //Thermocouple 2
// int vccPin2 = 11; //Copied above lines and added a 2 to thermocouple2 (thermoCLK2, thermoCS2, thermoDO2);
// int gndPin2 = 12; //also added a 2 to each vccPin2 and gndPin2 and set them to 51, 53. can change to other digital pins.

int led = 13;

//Display 1 uses vcc and gnd from 5v and gnd pin on board so we dont set a vccPin or a gndPin but you can if you want to.
// TM1637Display (CLK, DIO);
// int vccPin(name) = (pinhere)
// int gndPin(name) = (pinhere)


//TM1637Display2 (CLK2, DIO2); //Display 2
// int vccPin3 = 33; //Setting display2 CLK2, DIO2, vccPin3 and gndPin3.
// int gndPin3 = 35;


void setup() {
slave.begin( 19200);// 19200 baud, 8-bits, none, 1-bit stop
// use Arduino pins

// use Arduino pins
// pinMode(vccPin, OUTPUT); digitalWrite(vccPin, HIGH); //setting pinModes for vcc and gnd to Thermocouple 1
// pinMode(gndPin, OUTPUT); digitalWrite(gndPin, LOW);

// pinMode(vccPin2, OUTPUT); digitalWrite(vccPin2, HIGH); //setting pinModes for vcc and gnd to Thermocouple 2
// pinMode(gndPin2, OUTPUT); digitalWrite(gndPin2, LOW); //Notice 2's after vccPin2 and gndPin2

// pinMode(vccPin3, OUTPUT); digitalWrite(vccPin3, HIGH); //setting pinModes for vcc and gnd to display 2
// pinMode(gndPin3, OUTPUT); digitalWrite(gndPin3, LOW); //Notice 3's after vccPin3 and gndPin3

// pinMode(vccPin4, OUTPUT); digitalWrite(vccPin(name), HIGH); //if you use vccPin and gndPin for display 1 you can to set your pinModes here
// pinMode(gndPin(name), OUTPUT); digitalWrite(gndPin(name), LOW); //


Serial.println("MAX6675 test");
// wait for MAX chip to stabilize
delay(100);


}

void loop() {
display1.setBrightness (0x0f); //Display 1 void loop setup. Copied from TM1637 Library except for
uint8_t data[] = { 0x0, 0x0, 0x0, 0x0};
display1.setSegments (data);
delay (1);
int temp = (int) thermocouple.readFahrenheit(); //this line and //got these two lines from Robojax youtube video.
display1.showNumberDec (temp, true, 4, 0); //this line
//if you want to use Celsius, substitute .readFahrenheit with .readCelcius
//Changed display to display1 //and unblock
//Serial.print("C = ");
//Serial.println(thermocouple.readCelsius());
//below


display2.setBrightness (0x0f); //Display 2 void loop setup. Copied from above and changed
uint8_t data2[] = { 0x0, 0x0, 0x0, 0x0}; //changed data to data2
display2.setSegments (data); //display1 to display2
delay (1);
int temp2 = (int) thermocouple2.readFahrenheit(); //changed temp to temp2
display2.showNumberDec (temp2, true, 4, 0); //changed temp to temp2


//Thermocouple 1 Reading to serial print. Celsius blocked to read fahrenheit.

//Serial.print("C = ");
//Serial.println(thermocouple.readCelsius());
//Serial.print("F = ");
// Serial.println(thermocouple.readFahrenheit()); //Thermocouple 1 Reading

//Thermocouple 2 Reading to serial print. Celsius blocked to read fahrenheit.

//Serial.print("C = ");
//Serial.println(thermocouple2.readCelsius());
// Serial.print("F = ");
//Serial.println(thermocouple2.readFahrenheit()); //Thermocouple 2 Reading
//Notice thermocouple.readFahrenheit changed to thermocouple2.readFahranheit

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);


delay(5);}
}

maniel75

#10: Post by maniel75 » Sep 11, 2019, 12:21 am

Hello
My configuration is:

- Arduino Uno
- Thermocouple MAX6675 K
- Artisan 2.0
- Popcorn popper

Problem: I'm getting -1 for BT

my guess is that Artisan cannot read the temperature.

Thanks for your help

Image