/
ATmega48_Piezo_Sensor.ino
205 lines (179 loc) · 6.4 KB
/
ATmega48_Piezo_Sensor.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/*
Piezoelectric Z-Axis sensor using AtMega88/168/328 (AtMega 48 doesnt have enough memory for this version)
This sketch reads a piezo element to detect a touch of the printer's nozzle to the bed.
The sense pin is tied to an interrupt, which is pulled high by internal pullup resistor.
When the piezo touches the bed, the amplification circuit will draw the interrupt pin low
and the atmega will output a pulse based on the programmed trigger duration
* PD2 INT0 (Piezo In 'D2')
* PB1 PCINT1 (Trigger OUT 'D9')
* PC0 ADC0 (Voltage Reference Check 'A0')
* PC1 ADC1 (Sensitivity Adjustment Check 'A1')
* PD3 INT1 (Error feedback LED 'D3')
* PB6 PCINT6 (Voltage Adjustment Resistor 0 'D20')
* PB7 PCINT7 (Voltage Adjustment Resistor 1 'D21')
* PD5 T1 (Voltage Adjustment Resistor 2 'D5')
* PD6 PCINT22 (Voltage Adjustment Resistor 3 'D6')
created 1/8/2019
by Alan "pyr0ball" Weinstock
This code is in the public domain.
Based off examples from:
http://www.arduino.cc/en/Tutorial/Knock
http://www.circuitbasics.com/arduino-ohm-meter/
*/
// Set variables for working parameters
const int TRG_OUT = 9; // LED and Z-Min trigger output connected to digital pin 10
//const int TRG_OUT = 13; // For testing on Atmega328/2560, Output is moved to onboard LED pin
//#define Z_TRG 0 // the piezo is connected to INT0 / digital pin 2
const byte Z_TRG = 2;
int ERR_LED = 3; // LED will blink if optimal voltage range cannot be achieved
int InitCount = 6; // Number of times to blink the LED on start
int V_FOLLOW_PIN = A0; // Sense pin to check first amp stage voltage output
int VADJ_SENSE_PIN = A1; // Sense pin to check comparator stage voltage
int TRG_DUR = 120; // duration of the Z-axis pulse sent, in ms
int Vin = 5; // input reference voltage
float senseHighThrs = 2.47; // Upper threshold voltage of amp circuit before adjustment
float senseLowThrs = 1.90; // Lower threshold voltage of amp circuit before adjustment
const int VADJ_R0 = 20; // Auto-adjust ladder pin assignments
const int VADJ_R1 = 21;
const int VADJ_R2 = 5;
const int VADJ_R3 = 6;
// these variables will change on their own. Do not edit them
volatile int sensorHReading = 0; // variable to store the value read from the sensor pin
volatile int ADJ_STATE = 0; // Variable for voltage adjustment ladder
volatile int ERR_STATE = 0;
int folRead = 0;
float VRef = 0.00; // variable to store the value read from the reference voltage
int vadjRead = 0;
float VAdj = 0.00; // variable to store the value read from the second amp stage
int BlinkState = LOW;
int BlinkCount = InitCount * 2; // Multiply Blink count by 2 to handle toggle state
float diffAdjL = VAdj - senseLowThrs;
float diffAdjH = senseHighThrs - VAdj;
void setup() {
pinMode(TRG_OUT, OUTPUT); // declare the Trigger as as OUTPUT
pinMode(ERR_LED, OUTPUT);
pinMode(Z_TRG, INPUT_PULLUP); // declare z-sense input with pullup
pinMode(V_FOLLOW_PIN, INPUT);
pinMode(VADJ_SENSE_PIN, INPUT);
pinMode(VADJ_R0, INPUT); // declare input to break pull to ground
pinMode(VADJ_R1, INPUT); // declare input to break pull to ground
pinMode(VADJ_R2, INPUT); // declare input to break pull to ground
pinMode(VADJ_R3, INPUT); // declare input to break pull to ground
Serial.begin(9600);
// Uncomment the following lines to use PCInt pins instead of hardware interrupt
//#include <PinChangeInterrupt.h>
//attachPCINT(digitalPinToPCINT(Z_TRG), pulse, FALLING);
// Uncomment the followoing line to use hardware interrupt pin
attachInterrupt(digitalPinToInterrupt(Z_TRG), pulse, FALLING);
Serial.println("Initializing Piezo Sensor...");
}
void pulse() {
digitalWrite(TRG_OUT, HIGH);
sensorHReading = 1;
}
void adjustState() {
if (diffAdjL > 0.0) {
ADJ_STATE++;
}
if (diffAdjH > 0.0) {
ADJ_STATE--;
}
Serial.print("adjustState:");
Serial.println(ADJ_STATE);
Serial.println("--------------------");
}
void adjustVoltage() {
if (ADJ_STATE < 0) {
ERR_STATE = 1;
}
if (ADJ_STATE == 0) {
pinMode(VADJ_R3, INPUT);
pinMode(VADJ_R2, INPUT);
pinMode(VADJ_R1, INPUT);
pinMode(VADJ_R0, INPUT);
ERR_STATE = 0;
}
if (ADJ_STATE > 0) {
pinMode(VADJ_R3, OUTPUT);
digitalWrite(VADJ_R3, LOW);
pinMode(VADJ_R2, INPUT);
pinMode(VADJ_R1, INPUT);
pinMode(VADJ_R0, INPUT);
ERR_STATE = 0;
}
if (ADJ_STATE > 1) {
pinMode(VADJ_R2, OUTPUT);
digitalWrite(VADJ_R2, LOW);
pinMode(VADJ_R1, INPUT);
pinMode(VADJ_R0, INPUT);
ERR_STATE = 0;
}
if (ADJ_STATE > 2) {
pinMode(VADJ_R1, OUTPUT);
digitalWrite(VADJ_R1, LOW);
pinMode(VADJ_R0, INPUT);
ERR_STATE = 0;
}
if (ADJ_STATE > 3) {
pinMode(VADJ_R0, OUTPUT);
digitalWrite(VADJ_R0, LOW);
ERR_STATE = 0;
}
if (ADJ_STATE > 4) {
ERR_STATE = 1;
}
}
void checkError () {
if (ERR_STATE == 1) {
digitalWrite(ERR_LED, BlinkState);
BlinkState = !BlinkState;
}
if (ERR_STATE == 0) {
BlinkState = LOW;
digitalWrite(ERR_LED, BlinkState);
}
}
void loop() {
// Blink LED's on init
if (BlinkCount > 0) {
BlinkState = !BlinkState;
digitalWrite(ERR_LED, BlinkState);
digitalWrite(TRG_OUT, BlinkState);
delay(150);
--BlinkCount;
}
// Check voltage of first and second stages and compare against thresholds
folRead = analogRead(V_FOLLOW_PIN);
VRef = (folRead * 5.0) / 1024.0;
vadjRead = analogRead(VADJ_SENSE_PIN);
VAdj = (vadjRead * 5.0) / 1024.0;
diffAdjL = VAdj - senseLowThrs;
diffAdjH = senseHighThrs - VAdj;
// Voltage state adjustment
adjustState();
// Voltage divider adjustment
adjustVoltage();
// Check for error state
checkError();
// Checks state of the interrupt trigger, prints status, then sets output pin low
Serial.print("PZ Status:");
Serial.println(sensorHReading);
Serial.print("Voltage Reference:");
Serial.println(VRef);
Serial.print("Amp Sense:");
Serial.println(VAdj);
Serial.print("Adjustment State:");
Serial.println(ADJ_STATE);
Serial.print("Delay:");
Serial.println(TRG_DUR);
Serial.print("Low Diff:");
Serial.println(diffAdjL);
Serial.print("High Diff:");
Serial.println(diffAdjH);
Serial.print("Error State:");
Serial.println(ERR_STATE);
Serial.println("------------------");
delay(TRG_DUR);
digitalWrite(TRG_OUT, LOW);
sensorHReading = 0;
}