Components and supplies
Bench Power Supply, DC
OOTDTY 2 Channel SSR Solid State Relay High Lever Trigger 5A 5v12v For Uno R3 APR11_10
Arduino Ethernet Shield 2
Arduino Mega 2560
DC Small Dosing Pump 3V 6V 12V 24V Micro Self priming Mute Mini Peristaltic Liquid
Digital Load Cell Weight Sensor HX711 AD Converter Breakout Module 5KG Portable Electronic Kitchen Scale for Arduino Scale new Digital Load Cell Weight Sensor HX711 AD Converter Breakout Module 5KG Portable Electronic Kitchen Scale for Arduino Sca
Mini 5V Traffic Light LED Display Module for Arduino Red Yellow Green 5mm LED RG
Apps and platforms
WawiLib
Project description
Code
The final program.
arduino
1//------------------------------------------------------------ 2#include <WawiEthernet.h> 3// the media access control (ethernet hardware) address for the shield: 4byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x88 }; 5 6// the IP address of Arduino shield: 7byte ipArd[] = { 192, 168, 0, 88 }; 8 9// the communication port Arduino side for WawiLib communication 10unsigned int port = 49152; 11 12// the router's gateway address: 13byte gateway[] = { 10, 0, 0, 1 }; 14 15// the network subnet: 16byte subnet[] = { 255, 255, 225, 0 }; 17 18// declare communication object: 19EthernetServer server = EthernetServer(port); 20 21// WawiLib communications object: 22WawiEthernet WawiSrv; 23 24//------------------------------------------------------------ 25// HX711 scale load cell: 26#include "HX711.h" // credits to Bogdan Necula 27HX711 scale; 28const int LOADCELL_DOUT_PIN = 6; // HX711 data pin 29const int LOADCELL_SCK_PIN = 7; // HX711 clock pin 30bool triggerTare; 31 32#include "timer.h" 33WawiTimer tWdScale; // watchdog timer scale communication 34bool scaleOk=false; // scale communication status 35 36//------------------------------------------------------------ 37// Finite state machine variables: 38enum class FsmState { STEP0_IOTEST=0, STEP1_IDLE=1, STEP2_TARRA=2, STEP3_WAIT_CMD_FILL=3, STEP4_P_FILL_FAST=4, STEP5_P_FILL_SLOW=5, STEP6_WAIT=6, STEP7_WAIT_CMD_EMPTY=7, STEP8_P_EMPTY_FAST=8, STEP9_P_EMTPY_TIMEBASED=9, STEP10_ERROR=10 }; 39const char* stepStrings[] { "Step 0: Iotest", "Step 1: Idle", "Step 2: Tarra scale", "Step 3: Await cmd fill", "Step 4: Fill fast", "Step 5: Fill slow", "Step 6: Wait time", "Step 7: Await cmd empty", "Step 8: Empty fast", "Step 9: Empty time based", "Step 10: Error" }; 40char stepString[30]; 41FsmState stepCurrent,stepPrev; 42bool firstNewStep; 43 44// commands for finite state machine: 45bool cmdTarra; 46bool cmdFill; 47bool cmdEmpty; 48bool cmdClrError; 49 50// status variables 51bool errScale, errTimeout; 52 53// fill parameters 54float wFillMax=100; 55float wFillBatchFast=10; 56float wFillBatchSlow=5; 57float wActual, wTargetStep; 58 59unsigned long long tWdFillTimeout=30l*1000l; // 30 sec 60unsigned long long tWdEmptyTimeout=300l*1000l; // 300 sec 61 62WawiTimer tWdFsm; // watchdog timers for FSM time-out 63bool ledR=0,ledY=0,ledG=0; // LED control 64//------------------------------------------------------------ 65// digital outputs connected to solid state relays 1 and 2: 66#define DO_SSR_P1 8 67#define DO_SSR_P2 9 68 69// PWM ratio control pump operation: 70unsigned short pump1PwmFast=255; 71unsigned short pump2PwmFast=255; 72unsigned short pump1PwmSlow=128; 73unsigned short pump2PwmSlow=128; 74// actual value of SSR PWM setpoints: 75unsigned short pump1Pwm=0; 76unsigned short pump2Pwm=0; 77 78//------------------------------------------------------------ 79// digital outputs connected to solid state relays 1 and 2: 80#define DO_LED_RED 49 81#define DO_LED_YELLOW 47 82#define DO_LED_GREEN 45 83 84// blinker bit helper timers (software timers): 85WawiTimer tBlink250; // 250 ms on 86WawiTimer tBlink500; // 500 ms 87// blinking bits: 88bool blink250; 89bool blink500; 90 91//------------------------------------------------------------ 92// make variables of interest known to WawiLib: 93// this function is used in WawiSrv.begin(....) 94void wawiVarDef() 95{ 96 WawiSrv.wawiVar(triggerTare); 97 WawiSrv.wawiVar(scaleOk); 98 WawiSrv.wawiVar(tWdScale.m_act); 99 100 WawiSrv.wawiVar(cmdTarra); 101 WawiSrv.wawiVar(cmdFill); 102 WawiSrv.wawiVar(cmdEmpty); 103 WawiSrv.wawiVar(cmdClrError); 104 105 WawiSrv.wawiVar(errScale); 106 WawiSrv.wawiVar(errTimeout); 107 108 WawiSrv.wawiVar(wFillMax); 109 WawiSrv.wawiVar(wFillBatchFast); 110 WawiSrv.wawiVar(wFillBatchSlow); 111 WawiSrv.wawiVar(wActual); 112 WawiSrv.wawiVar(wTargetStep); 113 114 WawiSrv.wawiVar(tWdFillTimeout); 115 WawiSrv.wawiVar(tWdEmptyTimeout); 116 WawiSrv.wawiVar(tWdFsm); 117 118 WawiSrv.wawiVar(stepCurrent); 119 WawiSrv.wawiVar(stepPrev); 120 WawiSrv.wawiVarArray(stepString); 121 WawiSrv.wawiVar(stepString); 122 WawiSrv.wawiVar(tWdFsm.m_act); 123 124 WawiSrv.wawiVar(pump1PwmFast); 125 WawiSrv.wawiVar(pump2PwmFast); 126 WawiSrv.wawiVar(pump1PwmSlow); 127 WawiSrv.wawiVar(pump2PwmSlow); 128 WawiSrv.wawiVar(pump1Pwm); 129 WawiSrv.wawiVar(pump2Pwm); 130 131 WawiSrv.wawiVar(tBlink250.m_act); 132 WawiSrv.wawiVar(tBlink500.m_act); 133 WawiSrv.wawiVar(ledR); 134 WawiSrv.wawiVar(ledG); 135 WawiSrv.wawiVar(ledY); 136} 137 138//------------------------------------------------------------ 139// set finite state machine to other step: 140void FsmGoTo(FsmState newStep) 141{ 142 stepCurrent = newStep; 143 WawiSrv.println((String) "New step = "+ stepString + " (current weight=" +(String) wActual+")"); 144} 145 146//------------------------------------------------------------ 147// processing of scale (0..5KG) communication: 148void ScaleLoop() 149{ 150 // read weight, if available: 151 if (scale.is_ready()) 152 { 153 // read weight 154 wActual = scale.get_units(1); 155 // set watchdog: 156 tWdScale.setMs(1000); 157 // process tare cmd if required: 158 if (triggerTare) 159 { 160 // reset cmd to Tare: 161 triggerTare=0; 162 scale.tare(); 163 WawiSrv.print("Scale tare operation completed. "); 164 } 165 } 166 167 // process watchdog status: 168 if (scaleOk != !tWdScale.isZero()) 169 { 170 scaleOk = !tWdScale.isZero(); 171 if (scaleOk) 172 WawiSrv.println("Weight processing restarted, scale ok. "); 173 else 174 WawiSrv.println("Weight processing stopped, scale communication fault. "); 175 } 176 177 // loop part: 178 tWdScale.loop(); 179} 180 181//------------------------------------------------------------ 182// Finite state machine: 183void FsmLoop() 184{ 185 switch(stepCurrent) 186 { 187 //+++++++++++++++++++++++++++++++++++++++ 188 case FsmState::STEP0_IOTEST: 189 { 190 // no control of IO (for test purposes) 191 break; 192 } 193 //+++++++++++++++++++++++++++++++++++++++ 194 case FsmState::STEP1_IDLE: 195 { 196 if (cmdFill && !cmdTarra) FsmGoTo(FsmState::STEP3_WAIT_CMD_FILL); 197 if (cmdTarra) FsmGoTo(FsmState::STEP2_TARRA); 198 } 199 break; 200 201 //+++++++++++++++++++++++++++++++++++++++ 202 case FsmState::STEP2_TARRA: 203 { 204 // send cmd to ScaleLoop() 205 if (firstNewStep) 206 { 207 tWdFsm.setMs(1000); 208 triggerTare=true; 209 } 210 // cmd completed OK: 211 if (triggerTare==false) 212 FsmGoTo(FsmState::STEP3_WAIT_CMD_FILL); 213 214 if (tWdFsm.isZero()) 215 { 216 errTimeout=true; 217 WawiSrv.println("Error in step tarra scale: timout."); 218 FsmGoTo(FsmState::STEP10_ERROR); 219 } 220 if (scaleOk==false) 221 { 222 errScale=true; 223 WawiSrv.println("Error in step tarra scale: communication with scale failure."); 224 FsmGoTo(FsmState::STEP10_ERROR); 225 } 226 } 227 break; 228 229 //+++++++++++++++++++++++++++++++++++++++ 230 case FsmState::STEP3_WAIT_CMD_FILL: 231 { 232 if (cmdFill) 233 FsmGoTo(FsmState::STEP4_P_FILL_FAST); 234 } 235 break; 236 237 //+++++++++++++++++++++++++++++++++++++++ 238 case FsmState::STEP4_P_FILL_FAST: 239 { 240 if (firstNewStep) 241 { 242 tWdFsm.setMs(tWdFillTimeout); // timeout value for slow and fast filling 243 wTargetStep=wActual+wFillBatchFast; 244 } 245 246 if (wActual>wFillMax-wFillBatchSlow || wActual>wTargetStep) 247 FsmGoTo(FsmState::STEP5_P_FILL_SLOW); 248 249 if (tWdFsm.isZero()) 250 { 251 errTimeout=true; 252 WawiSrv.println("Error in step fill fast: timeout."); 253 FsmGoTo(FsmState::STEP10_ERROR); 254 } 255 } 256 break; 257 258 //+++++++++++++++++++++++++++++++++++++++ 259 case FsmState::STEP5_P_FILL_SLOW: 260 { 261 if (firstNewStep) 262 { 263 wTargetStep=wActual+wFillBatchSlow; 264 } 265 266 if (wActual>wFillMax || wActual>wTargetStep) 267 FsmGoTo(FsmState::STEP6_WAIT); 268 269 if (tWdFsm.isZero()) 270 { 271 errTimeout=true; 272 WawiSrv.println("Error in step fill slow: timeout."); 273 FsmGoTo(FsmState::STEP10_ERROR); 274 } 275 } 276 break; 277 278 //+++++++++++++++++++++++++++++++++++++++ 279 case FsmState::STEP6_WAIT: 280 { 281 if (firstNewStep) 282 tWdFsm.setMs(20000); 283 284 if (tWdFsm.isZero() && wActual<wFillMax) FsmGoTo(FsmState::STEP4_P_FILL_FAST); 285 if (tWdFsm.isZero() && wActual>=wFillMax) FsmGoTo(FsmState::STEP7_WAIT_CMD_EMPTY); 286 } 287 break; 288 289 //+++++++++++++++++++++++++++++++++++++++ 290 case FsmState::STEP7_WAIT_CMD_EMPTY: 291 { 292 if (cmdEmpty) FsmGoTo(FsmState::STEP8_P_EMPTY_FAST); 293 } 294 break; 295 296 //+++++++++++++++++++++++++++++++++++++++ 297 case FsmState::STEP8_P_EMPTY_FAST: 298 { 299 if (firstNewStep) 300 tWdFsm.setMs(tWdEmptyTimeout); 301 302 if (wActual<5) 303 FsmGoTo(FsmState::STEP9_P_EMTPY_TIMEBASED); 304 305 if (tWdFsm.isZero()) 306 { 307 errTimeout=true; 308 WawiSrv.println("Error in step empty fast: timeout."); 309 FsmGoTo(FsmState::STEP10_ERROR); 310 } 311 } 312 break; 313 314 //+++++++++++++++++++++++++++++++++++++++ 315 case FsmState::STEP9_P_EMTPY_TIMEBASED: 316 { 317 if (firstNewStep) tWdFsm.setMs(10000); // 10 seconds 318 319 if (tWdFsm.isZero()) 320 FsmGoTo(FsmState::STEP3_WAIT_CMD_FILL); 321 } 322 break; 323 324 //+++++++++++++++++++++++++++++++++++++++ 325 case FsmState::STEP10_ERROR: 326 { 327 if (cmdClrError) 328 { 329 FsmGoTo(FsmState::STEP1_IDLE); 330 errTimeout=false; 331 errScale=false; 332 cmdClrError=false; 333 } 334 } 335 break; 336 337 //+++++++++++++++++++++++++++++++++++++++ 338 default: 339 { 340 stepCurrent = FsmState::STEP1_IDLE; 341 break; 342 } 343 } 344 firstNewStep=(stepCurrent!=stepPrev); 345 stepPrev=stepCurrent; 346 strcpy(stepString,stepStrings[(int) stepCurrent]); 347 tWdFsm.loop(); 348} 349 350//---------------------------------------------------------------- 351// control I/O based on FSM step 352void IoLoop() 353{ 354 ledR=0; 355 switch(stepCurrent) 356 { 357 //+++++++++++++++++++++++++++++++++++++++ 358 case FsmState::STEP0_IOTEST: 359 // blink fast all leds = IO check 360 ledR=blink250; 361 ledY=blink250; 362 ledG=blink250; 363 break; 364 365 //+++++++++++++++++++++++++++++++++++++++ 366 case FsmState::STEP1_IDLE: 367 case FsmState::STEP3_WAIT_CMD_FILL: 368 case FsmState::STEP7_WAIT_CMD_EMPTY: 369 // yellow blink is wait for input/user intervention: 370 ledG=0; 371 ledR=0; 372 ledY=blink500; 373 pump1Pwm=0; 374 pump2Pwm=0; 375 break; 376 //+++++++++++++++++++++++++++++++++++++++ 377 case FsmState::STEP4_P_FILL_FAST: 378 pump1Pwm=pump1PwmFast; 379 pump2Pwm=0; 380 ledG=blink250; 381 ledR=0; 382 ledY=0; 383 break; 384 385 //+++++++++++++++++++++++++++++++++++++++ 386 case FsmState::STEP5_P_FILL_SLOW: 387 // green slow = pump slow 388 pump1Pwm=pump1PwmSlow; 389 pump2Pwm=0; 390 ledG=blink500; 391 ledR=0; 392 ledY=0; 393 break; 394 395 //+++++++++++++++++++++++++++++++++++++++ 396 case FsmState::STEP6_WAIT: 397 pump1Pwm=0; 398 pump2Pwm=0; 399 ledG=1; 400 ledR=0; 401 break; 402 //+++++++++++++++++++++++++++++++++++++++ 403 case FsmState::STEP8_P_EMPTY_FAST: 404 pump1Pwm=0; 405 pump2Pwm=pump2PwmFast; 406 ledG=blink250; 407 ledR=0; 408 ledY=0; 409 break; 410 411 //+++++++++++++++++++++++++++++++++++++++ 412 case FsmState::STEP9_P_EMTPY_TIMEBASED: 413 pump1Pwm=0; 414 pump2Pwm=pump2PwmSlow; 415 ledG=blink500; 416 ledR=0; 417 ledY=0; 418 break; 419 420 //+++++++++++++++++++++++++++++++++++++++ 421 case FsmState::STEP10_ERROR: 422 pump1Pwm=0; 423 pump2Pwm=0; 424 ledG=blink500; 425 ledR=0; 426 ledY=0; 427 break; 428 429 //+++++++++++++++++++++++++++++++++++++++ 430 default: 431 pump1Pwm=0; 432 pump2Pwm=0; 433 ledR=250; 434 ledY=0; 435 ledG=0; 436 break; 437 } 438 439 // limit pumpxPwm to range 0..255 440 pump1Pwm=min(pump1Pwm,255); 441 pump2Pwm=min(pump2Pwm,255); 442 443 // send pump value to IO: 444 analogWrite(DO_SSR_P1, 255-pump1Pwm); 445 analogWrite(DO_SSR_P2, 255-pump2Pwm); 446 447 // control the LED's 448 digitalWrite(DO_LED_RED,ledR); 449 digitalWrite(DO_LED_YELLOW,ledY); 450 digitalWrite(DO_LED_GREEN,ledG); 451} 452 453 454//------------------------------------------------------------ 455// create blinkbits: 456void UtilsLoop() 457{ 458 if (tBlink250.isZero()) 459 { 460 tBlink250.setMs(250); 461 blink250=!blink250; 462 } 463 if (tBlink500.isZero()) 464 { 465 tBlink500.setMs(500); 466 blink500=!blink500; 467 } 468 469 tBlink250.loop(); // 250 ms on 470 tBlink500.loop(); // 500 ms 471} 472 473//------------------------------------------------------------ 474void setup() 475{ 476 // init ethernet and WawiLib: 477 Ethernet.begin(mac, ipArd, gateway, subnet); 478 server.begin(); 479 WawiSrv.begin(wawiVarDef, server, "MyArduino"); 480 481 // init finit State machine: 482 FsmGoTo(FsmState::STEP1_IDLE); 483 stepPrev=FsmState::STEP0_IOTEST; 484 485 // init scale HX711: 486 scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN); 487 scale.set_scale(417.f); 488 489 // init PWM IO: 490 pinMode(DO_SSR_P1, OUTPUT); 491 pinMode(DO_SSR_P2, OUTPUT); 492 493 // LED IO 494 pinMode(DO_LED_RED,OUTPUT); 495 pinMode(DO_LED_YELLOW,OUTPUT); 496 pinMode(DO_LED_GREEN,OUTPUT); 497 498 // reduce PWM frequency to 30 hz 499 TCCR2B = TCCR2B & B11111000 | B00000111; // D9 to 30 Hz 500 TCCR4B = TCCR4B & B11111000 | B00000101; // D8 to 30 Hz 501} 502//------------------------------------------------------------ 503void loop() 504{ 505 // read weight of scale: 506 ScaleLoop(); 507 // finite state machine loop: 508 FsmLoop(); 509 // sent results to IO: 510 IoLoop(); 511 // varia (blinkbits ...) 512 UtilsLoop(); 513 // wawilib communication update: 514 WawiSrv.loop(); 515} 516
THE Program
arduino
1//------------------------------------------------------------ 2#include <WawiEthernet.h> 3// the media access control (ethernet hardware) address for the shield: 4byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x88 }; 5 6// the IP address of Arduino shield: 7byte ipArd[] = { 192, 168, 0, 88 }; 8 9// the communication port Arduino side for WawiLib communication 10unsigned int port = 49152; 11 12// the router's gateway address: 13byte gateway[] = { 10, 0, 0, 1 }; 14 15// the network subnet: 16byte subnet[] = { 255, 255, 225, 0 }; 17 18// declare communication object: 19EthernetServer server = EthernetServer(port); 20 21// WawiLib communications object: 22WawiEthernet WawiSrv; 23 24//------------------------------------------------------------ 25// HX711 scale load cell: 26#include "HX711.h" // credits to Bogdan Necula 27HX711 scale; 28const int LOADCELL_DOUT_PIN = 6; // HX711 data pin 29const int LOADCELL_SCK_PIN = 7; // HX711 clock pin 30bool triggerTare; 31 32#include "timer.h" 33WawiTimer tWdScale; // watchdog timer scale communication 34bool scaleOk=false; // scale communication status 35 36//------------------------------------------------------------ 37// Finite state machine variables: 38enum class FsmState { STEP0_IOTEST=0, STEP1_IDLE=1, STEP2_TARRA=2, STEP3_WAIT_CMD_FILL=3, STEP4_P_FILL_FAST=4, STEP5_P_FILL_SLOW=5, STEP6_WAIT=6, STEP7_WAIT_CMD_EMPTY=7, STEP8_P_EMPTY_FAST=8, STEP9_P_EMTPY_TIMEBASED=9, STEP10_ERROR=10 }; 39const char* stepStrings[] { "Step 0: Iotest", "Step 1: Idle", "Step 2: Tarra scale", "Step 3: Await cmd fill", "Step 4: Fill fast", "Step 5: Fill slow", "Step 6: Wait time", "Step 7: Await cmd empty", "Step 8: Empty fast", "Step 9: Empty time based", "Step 10: Error" }; 40char stepString[30]; 41FsmState stepCurrent,stepPrev; 42bool firstNewStep; 43 44// commands for finite state machine: 45bool cmdTarra; 46bool cmdFill; 47bool cmdEmpty; 48bool cmdClrError; 49 50// status variables 51bool errScale, errTimeout; 52 53// fill parameters 54float wFillMax=100; 55float wFillBatchFast=10; 56float wFillBatchSlow=5; 57float wActual, wTargetStep; 58 59unsigned long long tWdFillTimeout=30l*1000l; // 30 sec 60unsigned long long tWdEmptyTimeout=300l*1000l; // 300 sec 61 62WawiTimer tWdFsm; // watchdog timers for FSM time-out 63bool ledR=0,ledY=0,ledG=0; // LED control 64//------------------------------------------------------------ 65// digital outputs connected to solid state relays 1 and 2: 66#define DO_SSR_P1 8 67#define DO_SSR_P2 9 68 69// PWM ratio control pump operation: 70unsigned short pump1PwmFast=255; 71unsigned short pump2PwmFast=255; 72unsigned short pump1PwmSlow=128; 73unsigned short pump2PwmSlow=128; 74// actual value of SSR PWM setpoints: 75unsigned short pump1Pwm=0; 76unsigned short pump2Pwm=0; 77 78//------------------------------------------------------------ 79// digital outputs connected to solid state relays 1 and 2: 80#define DO_LED_RED 49 81#define DO_LED_YELLOW 47 82#define DO_LED_GREEN 45 83 84// blinker bit helper timers (software timers): 85WawiTimer tBlink250; // 250 ms on 86WawiTimer tBlink500; // 500 ms 87// blinking bits: 88bool blink250; 89bool blink500; 90 91//------------------------------------------------------------ 92// make variables of interest known to WawiLib: 93// this function is used in WawiSrv.begin(....) 94void wawiVarDef() 95{ 96 WawiSrv.wawiVar(triggerTare); 97 WawiSrv.wawiVar(scaleOk); 98 WawiSrv.wawiVar(tWdScale.m_act); 99 100 WawiSrv.wawiVar(cmdTarra); 101 WawiSrv.wawiVar(cmdFill); 102 WawiSrv.wawiVar(cmdEmpty); 103 WawiSrv.wawiVar(cmdClrError); 104 105 WawiSrv.wawiVar(errScale); 106 WawiSrv.wawiVar(errTimeout); 107 108 WawiSrv.wawiVar(wFillMax); 109 WawiSrv.wawiVar(wFillBatchFast); 110 WawiSrv.wawiVar(wFillBatchSlow); 111 WawiSrv.wawiVar(wActual); 112 WawiSrv.wawiVar(wTargetStep); 113 114 WawiSrv.wawiVar(tWdFillTimeout); 115 WawiSrv.wawiVar(tWdEmptyTimeout); 116 WawiSrv.wawiVar(tWdFsm); 117 118 WawiSrv.wawiVar(stepCurrent); 119 WawiSrv.wawiVar(stepPrev); 120 WawiSrv.wawiVarArray(stepString); 121 WawiSrv.wawiVar(stepString); 122 WawiSrv.wawiVar(tWdFsm.m_act); 123 124 WawiSrv.wawiVar(pump1PwmFast); 125 WawiSrv.wawiVar(pump2PwmFast); 126 WawiSrv.wawiVar(pump1PwmSlow); 127 WawiSrv.wawiVar(pump2PwmSlow); 128 WawiSrv.wawiVar(pump1Pwm); 129 WawiSrv.wawiVar(pump2Pwm); 130 131 WawiSrv.wawiVar(tBlink250.m_act); 132 WawiSrv.wawiVar(tBlink500.m_act); 133 WawiSrv.wawiVar(ledR); 134 WawiSrv.wawiVar(ledG); 135 WawiSrv.wawiVar(ledY); 136} 137 138//------------------------------------------------------------ 139// set finite state machine to other step: 140void FsmGoTo(FsmState newStep) 141{ 142 stepCurrent = newStep; 143 WawiSrv.println((String) "New step = "+ stepString + " (current weight=" +(String) wActual+")"); 144} 145 146//------------------------------------------------------------ 147// processing of scale (0..5KG) communication: 148void ScaleLoop() 149{ 150 // read weight, if available: 151 if (scale.is_ready()) 152 { 153 // read weight 154 wActual = scale.get_units(1); 155 // set watchdog: 156 tWdScale.setMs(1000); 157 // process tare cmd if required: 158 if (triggerTare) 159 { 160 // reset cmd to Tare: 161 triggerTare=0; 162 scale.tare(); 163 WawiSrv.print("Scale tare operation completed. "); 164 } 165 } 166 167 // process watchdog status: 168 if (scaleOk != !tWdScale.isZero()) 169 { 170 scaleOk = !tWdScale.isZero(); 171 if (scaleOk) 172 WawiSrv.println("Weight processing restarted, scale ok. "); 173 else 174 WawiSrv.println("Weight processing stopped, scale communication fault. "); 175 } 176 177 // loop part: 178 tWdScale.loop(); 179} 180 181//------------------------------------------------------------ 182// Finite state machine: 183void FsmLoop() 184{ 185 switch(stepCurrent) 186 { 187 //+++++++++++++++++++++++++++++++++++++++ 188 case FsmState::STEP0_IOTEST: 189 { 190 // no control of IO (for test purposes) 191 break; 192 } 193 //+++++++++++++++++++++++++++++++++++++++ 194 case FsmState::STEP1_IDLE: 195 { 196 if (cmdFill && !cmdTarra) FsmGoTo(FsmState::STEP3_WAIT_CMD_FILL); 197 if (cmdTarra) FsmGoTo(FsmState::STEP2_TARRA); 198 } 199 break; 200 201 //+++++++++++++++++++++++++++++++++++++++ 202 case FsmState::STEP2_TARRA: 203 { 204 // send cmd to ScaleLoop() 205 if (firstNewStep) 206 { 207 tWdFsm.setMs(1000); 208 triggerTare=true; 209 } 210 // cmd completed OK: 211 if (triggerTare==false) 212 FsmGoTo(FsmState::STEP3_WAIT_CMD_FILL); 213 214 if (tWdFsm.isZero()) 215 { 216 errTimeout=true; 217 WawiSrv.println("Error in step tarra scale: timout."); 218 FsmGoTo(FsmState::STEP10_ERROR); 219 } 220 if (scaleOk==false) 221 { 222 errScale=true; 223 WawiSrv.println("Error in step tarra scale: communication with scale failure."); 224 FsmGoTo(FsmState::STEP10_ERROR); 225 } 226 } 227 break; 228 229 //+++++++++++++++++++++++++++++++++++++++ 230 case FsmState::STEP3_WAIT_CMD_FILL: 231 { 232 if (cmdFill) 233 FsmGoTo(FsmState::STEP4_P_FILL_FAST); 234 } 235 break; 236 237 //+++++++++++++++++++++++++++++++++++++++ 238 case FsmState::STEP4_P_FILL_FAST: 239 { 240 if (firstNewStep) 241 { 242 tWdFsm.setMs(tWdFillTimeout); // timeout value for slow and fast filling 243 wTargetStep=wActual+wFillBatchFast; 244 } 245 246 if (wActual>wFillMax-wFillBatchSlow || wActual>wTargetStep) 247 FsmGoTo(FsmState::STEP5_P_FILL_SLOW); 248 249 if (tWdFsm.isZero()) 250 { 251 errTimeout=true; 252 WawiSrv.println("Error in step fill fast: timeout."); 253 FsmGoTo(FsmState::STEP10_ERROR); 254 } 255 } 256 break; 257 258 //+++++++++++++++++++++++++++++++++++++++ 259 case FsmState::STEP5_P_FILL_SLOW: 260 { 261 if (firstNewStep) 262 { 263 wTargetStep=wActual+wFillBatchSlow; 264 } 265 266 if (wActual>wFillMax || wActual>wTargetStep) 267 FsmGoTo(FsmState::STEP6_WAIT); 268 269 if (tWdFsm.isZero()) 270 { 271 errTimeout=true; 272 WawiSrv.println("Error in step fill slow: timeout."); 273 FsmGoTo(FsmState::STEP10_ERROR); 274 } 275 } 276 break; 277 278 //+++++++++++++++++++++++++++++++++++++++ 279 case FsmState::STEP6_WAIT: 280 { 281 if (firstNewStep) 282 tWdFsm.setMs(20000); 283 284 if (tWdFsm.isZero() && wActual<wFillMax) FsmGoTo(FsmState::STEP4_P_FILL_FAST); 285 if (tWdFsm.isZero() && wActual>=wFillMax) FsmGoTo(FsmState::STEP7_WAIT_CMD_EMPTY); 286 } 287 break; 288 289 //+++++++++++++++++++++++++++++++++++++++ 290 case FsmState::STEP7_WAIT_CMD_EMPTY: 291 { 292 if (cmdEmpty) FsmGoTo(FsmState::STEP8_P_EMPTY_FAST); 293 } 294 break; 295 296 //+++++++++++++++++++++++++++++++++++++++ 297 case FsmState::STEP8_P_EMPTY_FAST: 298 { 299 if (firstNewStep) 300 tWdFsm.setMs(tWdEmptyTimeout); 301 302 if (wActual<5) 303 FsmGoTo(FsmState::STEP9_P_EMTPY_TIMEBASED); 304 305 if (tWdFsm.isZero()) 306 { 307 errTimeout=true; 308 WawiSrv.println("Error in step empty fast: timeout."); 309 FsmGoTo(FsmState::STEP10_ERROR); 310 } 311 } 312 break; 313 314 //+++++++++++++++++++++++++++++++++++++++ 315 case FsmState::STEP9_P_EMTPY_TIMEBASED: 316 { 317 if (firstNewStep) tWdFsm.setMs(10000); // 10 seconds 318 319 if (tWdFsm.isZero()) 320 FsmGoTo(FsmState::STEP3_WAIT_CMD_FILL); 321 } 322 break; 323 324 //+++++++++++++++++++++++++++++++++++++++ 325 case FsmState::STEP10_ERROR: 326 { 327 if (cmdClrError) 328 { 329 FsmGoTo(FsmState::STEP1_IDLE); 330 errTimeout=false; 331 errScale=false; 332 cmdClrError=false; 333 } 334 } 335 break; 336 337 //+++++++++++++++++++++++++++++++++++++++ 338 default: 339 { 340 stepCurrent = FsmState::STEP1_IDLE; 341 break; 342 } 343 } 344 firstNewStep=(stepCurrent!=stepPrev); 345 stepPrev=stepCurrent; 346 strcpy(stepString,stepStrings[(int) stepCurrent]); 347 tWdFsm.loop(); 348} 349 350//---------------------------------------------------------------- 351// control I/O based on FSM step 352void IoLoop() 353{ 354 ledR=0; 355 switch(stepCurrent) 356 { 357 //+++++++++++++++++++++++++++++++++++++++ 358 case FsmState::STEP0_IOTEST: 359 // blink fast all leds = IO check 360 ledR=blink250; 361 ledY=blink250; 362 ledG=blink250; 363 break; 364 365 //+++++++++++++++++++++++++++++++++++++++ 366 case FsmState::STEP1_IDLE: 367 case FsmState::STEP3_WAIT_CMD_FILL: 368 case FsmState::STEP7_WAIT_CMD_EMPTY: 369 // yellow blink is wait for input/user intervention: 370 ledG=0; 371 ledR=0; 372 ledY=blink500; 373 pump1Pwm=0; 374 pump2Pwm=0; 375 break; 376 //+++++++++++++++++++++++++++++++++++++++ 377 case FsmState::STEP4_P_FILL_FAST: 378 pump1Pwm=pump1PwmFast; 379 pump2Pwm=0; 380 ledG=blink250; 381 ledR=0; 382 ledY=0; 383 break; 384 385 //+++++++++++++++++++++++++++++++++++++++ 386 case FsmState::STEP5_P_FILL_SLOW: 387 // green slow = pump slow 388 pump1Pwm=pump1PwmSlow; 389 pump2Pwm=0; 390 ledG=blink500; 391 ledR=0; 392 ledY=0; 393 break; 394 395 //+++++++++++++++++++++++++++++++++++++++ 396 case FsmState::STEP6_WAIT: 397 pump1Pwm=0; 398 pump2Pwm=0; 399 ledG=1; 400 ledR=0; 401 break; 402 //+++++++++++++++++++++++++++++++++++++++ 403 case FsmState::STEP8_P_EMPTY_FAST: 404 pump1Pwm=0; 405 pump2Pwm=pump2PwmFast; 406 ledG=blink250; 407 ledR=0; 408 ledY=0; 409 break; 410 411 //+++++++++++++++++++++++++++++++++++++++ 412 case FsmState::STEP9_P_EMTPY_TIMEBASED: 413 pump1Pwm=0; 414 pump2Pwm=pump2PwmSlow; 415 ledG=blink500; 416 ledR=0; 417 ledY=0; 418 break; 419 420 //+++++++++++++++++++++++++++++++++++++++ 421 case FsmState::STEP10_ERROR: 422 pump1Pwm=0; 423 pump2Pwm=0; 424 ledG=blink500; 425 ledR=0; 426 ledY=0; 427 break; 428 429 //+++++++++++++++++++++++++++++++++++++++ 430 default: 431 pump1Pwm=0; 432 pump2Pwm=0; 433 ledR=250; 434 ledY=0; 435 ledG=0; 436 break; 437 } 438 439 // limit pumpxPwm to range 0..255 440 pump1Pwm=min(pump1Pwm,255); 441 pump2Pwm=min(pump2Pwm,255); 442 443 // send pump value to IO: 444 analogWrite(DO_SSR_P1, 255-pump1Pwm); 445 analogWrite(DO_SSR_P2, 255-pump2Pwm); 446 447 // control the LED's 448 digitalWrite(DO_LED_RED,ledR); 449 digitalWrite(DO_LED_YELLOW,ledY); 450 digitalWrite(DO_LED_GREEN,ledG); 451} 452 453 454//------------------------------------------------------------ 455// create blinkbits: 456void UtilsLoop() 457{ 458 if (tBlink250.isZero()) 459 { 460 tBlink250.setMs(250); 461 blink250=!blink250; 462 } 463 if (tBlink500.isZero()) 464 { 465 tBlink500.setMs(500); 466 blink500=!blink500; 467 } 468 469 tBlink250.loop(); // 250 ms on 470 tBlink500.loop(); // 500 ms 471} 472 473//------------------------------------------------------------ 474void setup() 475{ 476 // init ethernet and WawiLib: 477 Ethernet.begin(mac, ipArd, gateway, subnet); 478 server.begin(); 479 WawiSrv.begin(wawiVarDef, server, "MyArduino"); 480 481 // init finit State machine: 482 FsmGoTo(FsmState::STEP1_IDLE); 483 stepPrev=FsmState::STEP0_IOTEST; 484 485 // init scale HX711: 486 scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN); 487 scale.set_scale(417.f); 488 489 // init PWM IO: 490 pinMode(DO_SSR_P1, OUTPUT); 491 pinMode(DO_SSR_P2, OUTPUT); 492 493 // LED IO 494 pinMode(DO_LED_RED,OUTPUT); 495 pinMode(DO_LED_YELLOW,OUTPUT); 496 pinMode(DO_LED_GREEN,OUTPUT); 497 498 // reduce PWM frequency to 30 hz 499 TCCR2B = TCCR2B & B11111000 | B00000111; // D9 to 30 Hz 500 TCCR4B = TCCR4B & B11111000 | B00000101; // D8 to 30 Hz 501} 502//------------------------------------------------------------ 503void loop() 504{ 505 // read weight of scale: 506 ScaleLoop(); 507 // finite state machine loop: 508 FsmLoop(); 509 // sent results to IO: 510 IoLoop(); 511 // varia (blinkbits ...) 512 UtilsLoop(); 513 // wawilib communication update: 514 WawiSrv.loop(); 515}
The final program.
arduino
1//------------------------------------------------------------ 2#include <WawiEthernet.h> 3// the media access control (ethernet hardware) address for the shield: 4byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x88 }; 5 6// the IP address of Arduino shield: 7byte ipArd[] = { 192, 168, 0, 88 }; 8 9// the communication port Arduino side for WawiLib communication 10unsigned int port = 49152; 11 12// the router's gateway address: 13byte gateway[] = { 10, 0, 0, 1 }; 14 15// the network subnet: 16byte subnet[] = { 255, 255, 225, 0 }; 17 18// declare communication object: 19EthernetServer server = EthernetServer(port); 20 21// WawiLib communications object: 22WawiEthernet WawiSrv; 23 24//------------------------------------------------------------ 25// HX711 scale load cell: 26#include "HX711.h" // credits to Bogdan Necula 27HX711 scale; 28const int LOADCELL_DOUT_PIN = 6; // HX711 data pin 29const int LOADCELL_SCK_PIN = 7; // HX711 clock pin 30bool triggerTare; 31 32#include "timer.h" 33WawiTimer tWdScale; // watchdog timer scale communication 34bool scaleOk=false; // scale communication status 35 36//------------------------------------------------------------ 37// Finite state machine variables: 38enum class FsmState { STEP0_IOTEST=0, STEP1_IDLE=1, STEP2_TARRA=2, STEP3_WAIT_CMD_FILL=3, STEP4_P_FILL_FAST=4, STEP5_P_FILL_SLOW=5, STEP6_WAIT=6, STEP7_WAIT_CMD_EMPTY=7, STEP8_P_EMPTY_FAST=8, STEP9_P_EMTPY_TIMEBASED=9, STEP10_ERROR=10 }; 39const char* stepStrings[] { "Step 0: Iotest", "Step 1: Idle", "Step 2: Tarra scale", "Step 3: Await cmd fill", "Step 4: Fill fast", "Step 5: Fill slow", "Step 6: Wait time", "Step 7: Await cmd empty", "Step 8: Empty fast", "Step 9: Empty time based", "Step 10: Error" }; 40char stepString[30]; 41FsmState stepCurrent,stepPrev; 42bool firstNewStep; 43 44// commands for finite state machine: 45bool cmdTarra; 46bool cmdFill; 47bool cmdEmpty; 48bool cmdClrError; 49 50// status variables 51bool errScale, errTimeout; 52 53// fill parameters 54float wFillMax=100; 55float wFillBatchFast=10; 56float wFillBatchSlow=5; 57float wActual, wTargetStep; 58 59unsigned long long tWdFillTimeout=30l*1000l; // 30 sec 60unsigned long long tWdEmptyTimeout=300l*1000l; // 300 sec 61 62WawiTimer tWdFsm; // watchdog timers for FSM time-out 63bool ledR=0,ledY=0,ledG=0; // LED control 64//------------------------------------------------------------ 65// digital outputs connected to solid state relays 1 and 2: 66#define DO_SSR_P1 8 67#define DO_SSR_P2 9 68 69// PWM ratio control pump operation: 70unsigned short pump1PwmFast=255; 71unsigned short pump2PwmFast=255; 72unsigned short pump1PwmSlow=128; 73unsigned short pump2PwmSlow=128; 74// actual value of SSR PWM setpoints: 75unsigned short pump1Pwm=0; 76unsigned short pump2Pwm=0; 77 78//------------------------------------------------------------ 79// digital outputs connected to solid state relays 1 and 2: 80#define DO_LED_RED 49 81#define DO_LED_YELLOW 47 82#define DO_LED_GREEN 45 83 84// blinker bit helper timers (software timers): 85WawiTimer tBlink250; // 250 ms on 86WawiTimer tBlink500; // 500 ms 87// blinking bits: 88bool blink250; 89bool blink500; 90 91//------------------------------------------------------------ 92// make variables of interest known to WawiLib: 93// this function is used in WawiSrv.begin(....) 94void wawiVarDef() 95{ 96 WawiSrv.wawiVar(triggerTare); 97 WawiSrv.wawiVar(scaleOk); 98 WawiSrv.wawiVar(tWdScale.m_act); 99 100 WawiSrv.wawiVar(cmdTarra); 101 WawiSrv.wawiVar(cmdFill); 102 WawiSrv.wawiVar(cmdEmpty); 103 WawiSrv.wawiVar(cmdClrError); 104 105 WawiSrv.wawiVar(errScale); 106 WawiSrv.wawiVar(errTimeout); 107 108 WawiSrv.wawiVar(wFillMax); 109 WawiSrv.wawiVar(wFillBatchFast); 110 WawiSrv.wawiVar(wFillBatchSlow); 111 WawiSrv.wawiVar(wActual); 112 WawiSrv.wawiVar(wTargetStep); 113 114 WawiSrv.wawiVar(tWdFillTimeout); 115 WawiSrv.wawiVar(tWdEmptyTimeout); 116 WawiSrv.wawiVar(tWdFsm); 117 118 WawiSrv.wawiVar(stepCurrent); 119 WawiSrv.wawiVar(stepPrev); 120 WawiSrv.wawiVarArray(stepString); 121 WawiSrv.wawiVar(stepString); 122 WawiSrv.wawiVar(tWdFsm.m_act); 123 124 WawiSrv.wawiVar(pump1PwmFast); 125 WawiSrv.wawiVar(pump2PwmFast); 126 WawiSrv.wawiVar(pump1PwmSlow); 127 WawiSrv.wawiVar(pump2PwmSlow); 128 WawiSrv.wawiVar(pump1Pwm); 129 WawiSrv.wawiVar(pump2Pwm); 130 131 WawiSrv.wawiVar(tBlink250.m_act); 132 WawiSrv.wawiVar(tBlink500.m_act); 133 WawiSrv.wawiVar(ledR); 134 WawiSrv.wawiVar(ledG); 135 WawiSrv.wawiVar(ledY); 136} 137 138//------------------------------------------------------------ 139// set finite state machine to other step: 140void FsmGoTo(FsmState newStep) 141{ 142 stepCurrent = newStep; 143 WawiSrv.println((String) "New step = "+ stepString + " (current weight=" +(String) wActual+")"); 144} 145 146//------------------------------------------------------------ 147// processing of scale (0..5KG) communication: 148void ScaleLoop() 149{ 150 // read weight, if available: 151 if (scale.is_ready()) 152 { 153 // read weight 154 wActual = scale.get_units(1); 155 // set watchdog: 156 tWdScale.setMs(1000); 157 // process tare cmd if required: 158 if (triggerTare) 159 { 160 // reset cmd to Tare: 161 triggerTare=0; 162 scale.tare(); 163 WawiSrv.print("Scale tare operation completed. "); 164 } 165 } 166 167 // process watchdog status: 168 if (scaleOk != !tWdScale.isZero()) 169 { 170 scaleOk = !tWdScale.isZero(); 171 if (scaleOk) 172 WawiSrv.println("Weight processing restarted, scale ok. "); 173 else 174 WawiSrv.println("Weight processing stopped, scale communication fault. "); 175 } 176 177 // loop part: 178 tWdScale.loop(); 179} 180 181//------------------------------------------------------------ 182// Finite state machine: 183void FsmLoop() 184{ 185 switch(stepCurrent) 186 { 187 //+++++++++++++++++++++++++++++++++++++++ 188 case FsmState::STEP0_IOTEST: 189 { 190 // no control of IO (for test purposes) 191 break; 192 } 193 //+++++++++++++++++++++++++++++++++++++++ 194 case FsmState::STEP1_IDLE: 195 { 196 if (cmdFill && !cmdTarra) FsmGoTo(FsmState::STEP3_WAIT_CMD_FILL); 197 if (cmdTarra) FsmGoTo(FsmState::STEP2_TARRA); 198 } 199 break; 200 201 //+++++++++++++++++++++++++++++++++++++++ 202 case FsmState::STEP2_TARRA: 203 { 204 // send cmd to ScaleLoop() 205 if (firstNewStep) 206 { 207 tWdFsm.setMs(1000); 208 triggerTare=true; 209 } 210 // cmd completed OK: 211 if (triggerTare==false) 212 FsmGoTo(FsmState::STEP3_WAIT_CMD_FILL); 213 214 if (tWdFsm.isZero()) 215 { 216 errTimeout=true; 217 WawiSrv.println("Error in step tarra scale: timout."); 218 FsmGoTo(FsmState::STEP10_ERROR); 219 } 220 if (scaleOk==false) 221 { 222 errScale=true; 223 WawiSrv.println("Error in step tarra scale: communication with scale failure."); 224 FsmGoTo(FsmState::STEP10_ERROR); 225 } 226 } 227 break; 228 229 //+++++++++++++++++++++++++++++++++++++++ 230 case FsmState::STEP3_WAIT_CMD_FILL: 231 { 232 if (cmdFill) 233 FsmGoTo(FsmState::STEP4_P_FILL_FAST); 234 } 235 break; 236 237 //+++++++++++++++++++++++++++++++++++++++ 238 case FsmState::STEP4_P_FILL_FAST: 239 { 240 if (firstNewStep) 241 { 242 tWdFsm.setMs(tWdFillTimeout); // timeout value for slow and fast filling 243 wTargetStep=wActual+wFillBatchFast; 244 } 245 246 if (wActual>wFillMax-wFillBatchSlow || wActual>wTargetStep) 247 FsmGoTo(FsmState::STEP5_P_FILL_SLOW); 248 249 if (tWdFsm.isZero()) 250 { 251 errTimeout=true; 252 WawiSrv.println("Error in step fill fast: timeout."); 253 FsmGoTo(FsmState::STEP10_ERROR); 254 } 255 } 256 break; 257 258 //+++++++++++++++++++++++++++++++++++++++ 259 case FsmState::STEP5_P_FILL_SLOW: 260 { 261 if (firstNewStep) 262 { 263 wTargetStep=wActual+wFillBatchSlow; 264 } 265 266 if (wActual>wFillMax || wActual>wTargetStep) 267 FsmGoTo(FsmState::STEP6_WAIT); 268 269 if (tWdFsm.isZero()) 270 { 271 errTimeout=true; 272 WawiSrv.println("Error in step fill slow: timeout."); 273 FsmGoTo(FsmState::STEP10_ERROR); 274 } 275 } 276 break; 277 278 //+++++++++++++++++++++++++++++++++++++++ 279 case FsmState::STEP6_WAIT: 280 { 281 if (firstNewStep) 282 tWdFsm.setMs(20000); 283 284 if (tWdFsm.isZero() && wActual<wFillMax) FsmGoTo(FsmState::STEP4_P_FILL_FAST); 285 if (tWdFsm.isZero() && wActual>=wFillMax) FsmGoTo(FsmState::STEP7_WAIT_CMD_EMPTY); 286 } 287 break; 288 289 //+++++++++++++++++++++++++++++++++++++++ 290 case FsmState::STEP7_WAIT_CMD_EMPTY: 291 { 292 if (cmdEmpty) FsmGoTo(FsmState::STEP8_P_EMPTY_FAST); 293 } 294 break; 295 296 //+++++++++++++++++++++++++++++++++++++++ 297 case FsmState::STEP8_P_EMPTY_FAST: 298 { 299 if (firstNewStep) 300 tWdFsm.setMs(tWdEmptyTimeout); 301 302 if (wActual<5) 303 FsmGoTo(FsmState::STEP9_P_EMTPY_TIMEBASED); 304 305 if (tWdFsm.isZero()) 306 { 307 errTimeout=true; 308 WawiSrv.println("Error in step empty fast: timeout."); 309 FsmGoTo(FsmState::STEP10_ERROR); 310 } 311 } 312 break; 313 314 //+++++++++++++++++++++++++++++++++++++++ 315 case FsmState::STEP9_P_EMTPY_TIMEBASED: 316 { 317 if (firstNewStep) tWdFsm.setMs(10000); // 10 seconds 318 319 if (tWdFsm.isZero()) 320 FsmGoTo(FsmState::STEP3_WAIT_CMD_FILL); 321 } 322 break; 323 324 //+++++++++++++++++++++++++++++++++++++++ 325 case FsmState::STEP10_ERROR: 326 { 327 if (cmdClrError) 328 { 329 FsmGoTo(FsmState::STEP1_IDLE); 330 errTimeout=false; 331 errScale=false; 332 cmdClrError=false; 333 } 334 } 335 break; 336 337 //+++++++++++++++++++++++++++++++++++++++ 338 default: 339 { 340 stepCurrent = FsmState::STEP1_IDLE; 341 break; 342 } 343 } 344 firstNewStep=(stepCurrent!=stepPrev); 345 stepPrev=stepCurrent; 346 strcpy(stepString,stepStrings[(int) stepCurrent]); 347 tWdFsm.loop(); 348} 349 350//---------------------------------------------------------------- 351// control I/O based on FSM step 352void IoLoop() 353{ 354 ledR=0; 355 switch(stepCurrent) 356 { 357 //+++++++++++++++++++++++++++++++++++++++ 358 case FsmState::STEP0_IOTEST: 359 // blink fast all leds = IO check 360 ledR=blink250; 361 ledY=blink250; 362 ledG=blink250; 363 break; 364 365 //+++++++++++++++++++++++++++++++++++++++ 366 case FsmState::STEP1_IDLE: 367 case FsmState::STEP3_WAIT_CMD_FILL: 368 case FsmState::STEP7_WAIT_CMD_EMPTY: 369 // yellow blink is wait for input/user intervention: 370 ledG=0; 371 ledR=0; 372 ledY=blink500; 373 pump1Pwm=0; 374 pump2Pwm=0; 375 break; 376 //+++++++++++++++++++++++++++++++++++++++ 377 case FsmState::STEP4_P_FILL_FAST: 378 pump1Pwm=pump1PwmFast; 379 pump2Pwm=0; 380 ledG=blink250; 381 ledR=0; 382 ledY=0; 383 break; 384 385 //+++++++++++++++++++++++++++++++++++++++ 386 case FsmState::STEP5_P_FILL_SLOW: 387 // green slow = pump slow 388 pump1Pwm=pump1PwmSlow; 389 pump2Pwm=0; 390 ledG=blink500; 391 ledR=0; 392 ledY=0; 393 break; 394 395 //+++++++++++++++++++++++++++++++++++++++ 396 case FsmState::STEP6_WAIT: 397 pump1Pwm=0; 398 pump2Pwm=0; 399 ledG=1; 400 ledR=0; 401 break; 402 //+++++++++++++++++++++++++++++++++++++++ 403 case FsmState::STEP8_P_EMPTY_FAST: 404 pump1Pwm=0; 405 pump2Pwm=pump2PwmFast; 406 ledG=blink250; 407 ledR=0; 408 ledY=0; 409 break; 410 411 //+++++++++++++++++++++++++++++++++++++++ 412 case FsmState::STEP9_P_EMTPY_TIMEBASED: 413 pump1Pwm=0; 414 pump2Pwm=pump2PwmSlow; 415 ledG=blink500; 416 ledR=0; 417 ledY=0; 418 break; 419 420 //+++++++++++++++++++++++++++++++++++++++ 421 case FsmState::STEP10_ERROR: 422 pump1Pwm=0; 423 pump2Pwm=0; 424 ledG=blink500; 425 ledR=0; 426 ledY=0; 427 break; 428 429 //+++++++++++++++++++++++++++++++++++++++ 430 default: 431 pump1Pwm=0; 432 pump2Pwm=0; 433 ledR=250; 434 ledY=0; 435 ledG=0; 436 break; 437 } 438 439 // limit pumpxPwm to range 0..255 440 pump1Pwm=min(pump1Pwm,255); 441 pump2Pwm=min(pump2Pwm,255); 442 443 // send pump value to IO: 444 analogWrite(DO_SSR_P1, 255-pump1Pwm); 445 analogWrite(DO_SSR_P2, 255-pump2Pwm); 446 447 // control the LED's 448 digitalWrite(DO_LED_RED,ledR); 449 digitalWrite(DO_LED_YELLOW,ledY); 450 digitalWrite(DO_LED_GREEN,ledG); 451} 452 453 454//------------------------------------------------------------ 455// create blinkbits: 456void UtilsLoop() 457{ 458 if (tBlink250.isZero()) 459 { 460 tBlink250.setMs(250); 461 blink250=!blink250; 462 } 463 if (tBlink500.isZero()) 464 { 465 tBlink500.setMs(500); 466 blink500=!blink500; 467 } 468 469 tBlink250.loop(); // 250 ms on 470 tBlink500.loop(); // 500 ms 471} 472 473//------------------------------------------------------------ 474void setup() 475{ 476 // init ethernet and WawiLib: 477 Ethernet.begin(mac, ipArd, gateway, subnet); 478 server.begin(); 479 WawiSrv.begin(wawiVarDef, server, "MyArduino"); 480 481 // init finit State machine: 482 FsmGoTo(FsmState::STEP1_IDLE); 483 stepPrev=FsmState::STEP0_IOTEST; 484 485 // init scale HX711: 486 scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN); 487 scale.set_scale(417.f); 488 489 // init PWM IO: 490 pinMode(DO_SSR_P1, OUTPUT); 491 pinMode(DO_SSR_P2, OUTPUT); 492 493 // LED IO 494 pinMode(DO_LED_RED,OUTPUT); 495 pinMode(DO_LED_YELLOW,OUTPUT); 496 pinMode(DO_LED_GREEN,OUTPUT); 497 498 // reduce PWM frequency to 30 hz 499 TCCR2B = TCCR2B & B11111000 | B00000111; // D9 to 30 Hz 500 TCCR4B = TCCR4B & B11111000 | B00000101; // D8 to 30 Hz 501} 502//------------------------------------------------------------ 503void loop() 504{ 505 // read weight of scale: 506 ScaleLoop(); 507 // finite state machine loop: 508 FsmLoop(); 509 // sent results to IO: 510 IoLoop(); 511 // varia (blinkbits ...) 512 UtilsLoop(); 513 // wawilib communication update: 514 WawiSrv.loop(); 515} 516
Downloadable files
SSR
SSR
SSR power section
SSR power section
Scale
Scale
Scale
Scale
SSR power section
SSR power section
SSR
SSR
Comments
Only logged in users can leave comments
Anonymous user
3 years ago
SELAMLAR. PAYLAŞTIĞINIZ İÇİN,SİZE VE ŞAHSINIZDA EMEĞİ GEÇEN TÜM ARKADAŞLARA ÇOK TEŞEKKÜR EDERİM. SAĞLIK VE BAŞARI DOLU ÖMÜRLER.
pogiakodin
3 months ago
Subject: Inquiry for Custom Doser with Peristaltic Pumps Dear user1793315, I hope this email finds you well. My name is Sherwin Abela and I am the owner and bartender of a small coffee shop. I am reaching out to inquire about the possibility of acquiring a custom doser with a touch screen and 4 peristaltic pumps for our shop. As a small business owner, I have noticed that the process of making iced coffee can be time-consuming, and at times, it can lead to customer dissatisfaction due to the wait time. In order to improve efficiency and customer satisfaction, I am interested in exploring the option of a custom doser with 4 peristaltic pumps, each for dispensing different liquid ingredients from 4 separate containers. I would appreciate it if you could provide me with information regarding the customization options available, including the features of the touch screen interface and the capacity of the containers. Additionally, I am interested in learning about the pricing and any potential lead time for the customization process. Furthermore, if possible, I would like to schedule a meeting or call to discuss the specifications in more detail and to address any questions or concerns that may arise. I understand that customization of this nature may require detailed discussions and planning, and I am committed to working closely with your team to ensure that the final product meets the specific needs of our coffee shop. I look forward to your prompt response and the opportunity to explore the possibility of collaborating with your company for this custom doser solution. Thank you for your attention to this matter. Sincerely, Sherwin Abela +639761272213