Skip to content

Instantly share code, notes, and snippets.

@tspspi
Created October 14, 2019 13:21
Show Gist options
  • Save tspspi/e64c86991136de1d8a37cd952bb8d3fe to your computer and use it in GitHub Desktop.
Save tspspi/e64c86991136de1d8a37cd952bb8d3fe to your computer and use it in GitHub Desktop.
3D printer piezo board leveling Arduino test sketch
/*
Simple test program for 3D printer piezo
bed leveling adapter board described at
https://www.tspi.at/2019/09/11/piezobedlevel.html
(using Arduino IDE and libraries).
This does not provide any I2C connectivity, etc.
and just periodically reads analog samples, dumps
them to the serial port and does some moving average
filtering (as well as using a inductive probe as
veto to suppress triggering while moving)
*/
#define ANALOGPIN_IN0 A0
#define ANALOGPIN_IN1 A1
#define ANALOGPIN_IN2 A2
#define ANALOGPIN_IN3 A3
#define DIGITAL_OUT 9
#define INDUC_IN 10
#define TRIGGERDEVIATION 15
static int movingAverageState[4];
static int measuredCenterlines[4];
static int initsamples;
void setup() {
Serial.begin(9600);
// Set output pin
pinMode(DIGITAL_OUT, OUTPUT);
pinMode(INDUC_IN, INPUT);
movingAverageState[0] = analogRead(ANALOGPIN_IN0);
movingAverageState[1] = analogRead(ANALOGPIN_IN1);
movingAverageState[2] = analogRead(ANALOGPIN_IN2);
movingAverageState[3] = analogRead(ANALOGPIN_IN3);
double avg[4];
avg[0] = 0.0;
avg[1] = 0.0;
avg[2] = 0.0;
avg[3] = 0.0;
for(initsamples = 0; initsamples < 1000; initsamples = initsamples + 1) {
avg[0] = avg[0] + ((double)analogRead(ANALOGPIN_IN0)) / ((double)1000);
avg[1] = avg[1] + ((double)analogRead(ANALOGPIN_IN1)) / ((double)1000);
avg[2] = avg[2] + ((double)analogRead(ANALOGPIN_IN2)) / ((double)1000);
avg[3] = avg[3] + ((double)analogRead(ANALOGPIN_IN3)) / ((double)1000);
}
Serial.print("Init samples (averages): ");
Serial.print((int)avg[0]);
Serial.print(" ");
Serial.print((int)avg[1]);
Serial.print(" ");
Serial.print((int)avg[2]);
Serial.print(" ");
Serial.println((int)avg[3]);
measuredCenterlines[0] = (int)avg[0];
measuredCenterlines[1] = (int)avg[1];
measuredCenterlines[2] = (int)avg[2];
measuredCenterlines[3] = (int)avg[3];
}
static int debounceCounter = 12;
#define movingAverageAlpha 0.4f
void loop() {
int aValue[4];
aValue[0] = analogRead(ANALOGPIN_IN0);
aValue[1] = analogRead(ANALOGPIN_IN1);
aValue[2] = analogRead(ANALOGPIN_IN2);
aValue[3] = analogRead(ANALOGPIN_IN3);
movingAverageState[0] = movingAverageAlpha*aValue[0] + (1.0f - movingAverageAlpha)*movingAverageState[0];
movingAverageState[1] = movingAverageAlpha*aValue[1] + (1.0f - movingAverageAlpha)*movingAverageState[1];
movingAverageState[2] = movingAverageAlpha*aValue[2] + (1.0f - movingAverageAlpha)*movingAverageState[2];
movingAverageState[3] = movingAverageAlpha*aValue[3] + (1.0f - movingAverageAlpha)*movingAverageState[3];
int trigCount = 0;
int measValues[4];
for(int i = 0; i < 4; i++) {
measValues[i] = movingAverageState[i] - measuredCenterlines[i];
}
Serial.print(measValues[0]);
Serial.print(" ");
Serial.print(measValues[1]);
Serial.print(" ");
Serial.print(measValues[2]);
Serial.print(" ");
Serial.println(measValues[3]);
for(int i = 0; i < 4; i++) {
if(measValues[i] < 0) { measValues[i] = measValues[i] * -1; }
}
for(int i = 0; i < 4; i++) {
if(measValues[i] > TRIGGERDEVIATION) { trigCount++; }
}
if((trigCount >= 1) && digitalRead(INDUC_IN)) {
debounceCounter = 12;
}
if(debounceCounter > 0) {
digitalWrite(DIGITAL_OUT, HIGH);
debounceCounter--;
} else {
digitalWrite(DIGITAL_OUT, LOW);
}
delay(5);
}
@tspspi
Copy link
Author

tspspi commented Oct 25, 2020

Just to add that: Even that code should work unmodified if one pulls the input for the unconnected piezo to GND or VCC so no random noise is measured - I've actually done that during testing a few times.

@sergiofagundes
Copy link

sergiofagundes commented Oct 26, 2020

Thanks for replying. I have remixed your board for using the Attiny85 instead. When I have it done I'll post my testings here.
I'm planning to disable the Attiny85 reset pin, and get 2 extra pins to create a threshold setup pins to easily tune the board without reprogramming the attiny85. Of course, I need to change the code to matches the t85 pinout. I have done this for the JohnSL
/ FSR_Endstop too, but the FSR sensors it's not cheap here where I live (it's about US$16 each, where the Piezo costs only $1.6 each).

tiny85_piezo_sensor

@tspspi
Copy link
Author

tspspi commented Oct 26, 2020

Yeah having a reset method is pretty useful - I've added this (but not uploaded here up until now, maybe I should do this) to my own implementation too using I2C (since most components of my custom machine communicate via I2C anyways). I'd be really interested in how well that approach works for your machine too - since the only "experience" I made with this is unfortunately my own custom designed machine.

Yep, the price and also the constraints by having an capacitive sensor mounted onto the printhead also was a reason I tried to operate without one - I think it should be possible with more fancy signal processing (for example if I hear correctly I have an fan mounted onto my printhead that seems to change frequency in case of a touch event - it should be possible to detect that) - and of course also to discriminate for noise so one doesn't need any other additional sensor - I didn't follow that route though since the capacitive sensor already had been in place so there was no need for that though it would be really interesting if this works well (and after print has started one could of course disable or ignore endstop triggering as usual; Maybe it would also be possible to simply do some statistics to remove noisy triggering by the piezos to by modifying the tramming process ...)

@tspspi
Copy link
Author

tspspi commented Oct 26, 2020

Maybe just another comment about "biasing" the piezos that way - depending on the piezos this works pretty well but when one drives the input of the AVR directly with them one relies on the protection diodes to catch voltage spikes that might arise when larger forces are acting on the piezos - also one cannot use typical industrial sensors that way, it works pretty well with piezo disks that are thought as guitar pickups or speakers though usually but of course there is no guarantee that a specific type doesn't deliver voltages too large for an AVR to handle. It's never been a problem for my setups (even when dropping tools on the print surface, etc.) with different disks but I think it's worth to mention

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment