tobias's point of view |
Main »
Computers-software-arduino-stepper Winderino /* * License: GPLv3 * by tom * * built on linux using arduino ide v1.8.5 * for the ESP8266 NodeMCU LUA CP2102 ESP-12E w/ cpu 80mhz * * * $Id: stepper_winder.ino,v 1.17.1.4 2018/06/08 18:34:42 me Exp me $ */ #include <AccelStepper.h> // driver for the stepper 28BYJ-48 5v steppers #define HALFSTEP 8 #include <ESP8266WiFi.h> #include <TimeLib.h> #include <time.h> // only used for time(nullptr), which seems to set the rtc from ntp on the esp8266 !??! #include "SSD1306.h" // alias for `#include "SSD1306Wire.h"` SSD1306 display(0x3c, D2, D1); // i2c oled nodeMCU pin mapping D2->sda, D1->scl ; can't put this in 'setup' ? #define ACTION_LED_PIN LED_BUILTIN #define CONNECTION_LED_PIN 2 // -- set as needed: const char* ssid = "YourAPgoesHere"; const char* password = "YourPasswordGoesHere"; const int timezone = -8; // pst ... change to yours. const unsigned int tpd = 1600; // rotations per day in either direction. const unsigned int rot = 3; // how many rotations we want. // -- our constants below long int prevDisplay = 0; // used in loop to see if time has changed const unsigned long int timeSyncNist = 60*10*1000; // 600,000ms is mins between getting nist time const unsigned long int myConnSpeed = 500000; // this is the serial connection speed. unsigned int dst = 0; // we start at zero and auto set via dstSet() below. boolean update_tm = 1; boolean done_rot = 0; boolean toggleAction = false; long int oldPosition = 10; unsigned long int rcntCW = 0; // counts the CW rotations of the servo. unsigned long int rcntCCW = 0; // counts the CCW rotations of the servo. unsigned long int hrs24Millis = 24*60*60*1000; // we start with 24hrs in ms const unsigned int sleepBtwnTurns = ( (24*60*60) / (tpd/(rot*2)) )*1000; // (minsDay/(tpd/rotGroup))*1000ms; 324,000ms ~5mins @ 1600tpd this is how long we sleep in ms, between turning groups. unsigned long previousMillis = 0; unsigned long previousNistMillis = 0; // sync with nist time. unsigned long int k = 0; // used to see if we should get re sync'd with nist time server timeSyncNist 60 - min unsigned int m = 0; // used to count wifi connect tries. String myVersion ="$Revision: 1.17.1.4 $"; // this will change with each rcs ci String myVersionNumber = myVersion.substring(11,20); time_t tNow; // Switch pin definitions NOTE: don't use gpio 9,10 #define enter_button D3 // gpio 0 can't be low at power up. #define up_button 2 // gpio 2 #define down_button 10 // gpio 10 // Motor pin definitions #define motorPin1 D5 // IN1 on the ULN2003 driver 1 #define motorPin2 D6 // IN2 on the ULN2003 driver 1 #define motorPin3 D7 // IN3 on the ULN2003 driver 1 #define motorPin4 D8 // IN4 on the ULN2003 driver 1 // Initialize with pin sequence IN1-IN3-IN2-IN4 for using the AccelStepper with 28BYJ-48 AccelStepper stepper1(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4); void setup() { stepper1.setMaxSpeed(900.0); stepper1.setAcceleration(100.0); // orig acc was '100' gives about 3.5sec startup and 3.5sec startdown stepper1.setSpeed(900); // 28BYJ-48 max 800pps or about 5sec/rev max ... stepper1.moveTo(rot*4096); // 4096 seems to be one revolution. 4076 some say this is one revolution, seemed a little short. pinMode(enter_button, INPUT); pinMode(enter_button, INPUT_PULLUP); // connect internal pull-up // pinMode(up_button, INPUT); // pinMode(up_button, INPUT_PULLUP); // digitalWrite(up_button, HIGH); // connect internal pull-up // pinMode(down_button, INPUT); // digitalWrite(down_button, HIGH); // connect internal pull-up display.init(); display.flipScreenVertically(); display.setContrast(255); pinMode(ACTION_LED_PIN, OUTPUT); pinMode(CONNECTION_LED_PIN, OUTPUT); SetConnectionLEDOff(); // make sure we start in off as we haven't logged into wifi yet. SetActionLEDOn(); // show we are in setup or active. Serial.begin(myConnSpeed); delay(100); wifiUP("v"+String(myVersionNumber)+": First try ... "); if(nistTime()){ // set our time of day up. dstSet(); // set dst if we have a good rtc/nist time. nistTime(); // re set it after we have dst set. } }//--(end setup )--- void SetActionLEDOn(){ digitalWrite(ACTION_LED_PIN, false);} void SetActionLEDOff(){ digitalWrite(ACTION_LED_PIN, true); } void SetConnectionLEDOn(){ digitalWrite(CONNECTION_LED_PIN, false); } void SetConnectionLEDOff(){ digitalWrite(CONNECTION_LED_PIN, true); } boolean button_debounce(int button) { Serial.print("got a button push on "+String(button)); while( ! digitalRead(button) ) { delay(10); } delay(5); while( ! digitalRead(button) ) { delay(10); } Serial.print(". Just debounced button: "); Serial.println(String(button)); } // end of function button_debounce void loop() { if( ! digitalRead(enter_button) ){button_debounce(enter_button);} // if( ! digitalRead(up_button) ){button_debounce(up_button);} // if( ! digitalRead(down_button) ){button_debounce(down_button);} //-- section to move the steppers if needed, this runs as fast at the loop will run, but the calls to stepper1 do not. if ( (stepper1.distanceToGo() == 0) && ! done_rot){ stepper1.moveTo(0); // lets go ccw, ie the oppisite direction. done_rot = 1; } // flag that we've done the cw and still need to do the ccw if ( (stepper1.distanceToGo()) == 0 && done_rot ) { stepper1.disableOutputs(); } // if we've made our rotation turn stepper off. else{ stepper1.run(); if ( ! (stepper1.currentPosition() % (4096)) && (stepper1.currentPosition()!= oldPosition) ){ oldPosition = stepper1.currentPosition(); if ( done_rot ){++rcntCCW;} else{++rcntCW;} } } // end of section on moving the steppers. //-- display update section, only if the seconds have changed. tNow = time(nullptr); // store the current time in 'tNow'. epoch seconds if ( tNow != prevDisplay){ //update the display only if the time has changed{ prevDisplay = tNow; // seconds since epoch. display.clear(); oled(); display.display(); // Display it on the screen if ( toggleAction ){ SetActionLEDOff(); toggleAction = false; } // toggles the red led so we now we have heartbeat else { SetActionLEDOn(); toggleAction = true; } } // end of section to update display. //-- start of rotation group every 'sleepBtwnTruns' ms ie every 162,000 ms for 3200 tpd (turns per day). if( (unsigned long)(millis() - previousMillis) >= sleepBtwnTurns ){ // 324,000ms for 1600 tpd sleep between rotation groups previousMillis = millis(); SetActionLEDOn(); if (stepper1.distanceToGo() == 0) { //Change direction when the stepper reaches the target position stepper1.enableOutputs(); // turn the stepper back on. stepper1.moveTo(rot*4096); // lets go cw done_rot = 0; // flag that we've done our rot group. } Serial.print("sleeping for "); Serial.print(sleepBtwnTurns/1000/60); Serial.println(" mins before next turn group."); } // end of start rotation check. //-- resync with nist every 'timeSyncNist' ms ... 10 mins seems good. if( (unsigned long)(millis() - previousNistMillis) >= (timeSyncNist)){ // 600,0000ms every 10 mins if (WiFi.status() != WL_CONNECTED) { //if we drop wifi, can't do below. tNow = time(nullptr); String timeNow = String(hourFormat12(tNow))+":"+twoDigits(minute(tNow))+":"+twoDigits(second(tNow)); Serial.print(timeNow); // displays 'Thur Dec 14 13:52:05 2017' wifiUP("v"+String(myVersionNumber)+": dropped, we try again ... "); } // v1.17.1.4 else{ Serial.print("wifi is up."); SetConnectionLEDOn(); Serial.print(" checking nist time: "); tNow = time(nullptr); String timeNow = String(hourFormat12(tNow))+":"+twoDigits(minute(tNow))+":"+twoDigits(second(tNow)); Serial.println(timeNow); // displays 'Thur Dec 14 13:52:05 2017' dstSet(); // -- change dst varible march and november and startup nistTime(); // -- sync with nist/ntp } previousNistMillis = millis(); // sync with nist, sync or no sync we wait 10mins to do it again. } // end of nist ntp check. // -- reset rotation counters ever 24hrs from startup if( (unsigned long)(millis() - hrs24Millis) >= 24*60*60*1000 ){ // has it been 24hrs in ms since we started ? hrs24Millis = millis(); rcntCCW = 0; rcntCW = 0; } // end of rotation count reset check } //--- end of main loop. //================= functions boolean nistTime(){ if (WiFi.status() == WL_CONNECTED) { tNow = time(nullptr); String timeNow = (String(hourFormat12(tNow))+":"+String(twoDigits(minute(tNow)))+":"+String(twoDigits(second(tNow)))+", "+monthShortStr(month(tNow))+"-"+String(day(tNow))+"-"+String(year(tNow)) ); Serial.println("our current time is: "+timeNow); Serial.print("Getting nist time."); configTime((timezone * 60*60),(dst * 60*60), "pool.ntp.org", "time.nist.gov"); // set the chips rtc from nist delay(2000); int i = 0; while ((time(nullptr) < 1522565410) && i < 15) { // 1522565410 sec = April 1, 2018 6:50:10 AM Serial.print("."); delay(1000); i++; } if(i >= 15){Serial.println("");Serial.println("getting nist time failed. No responce from query.");return(false);} tNow = time(nullptr); timeNow = (String(hourFormat12(tNow))+":"+String(twoDigits(minute(tNow)))+":"+String(twoDigits(second(tNow)))+", "+monthShortStr(month(tNow))+"-"+String(day(tNow))+"-"+String(year(tNow)) ); Serial.print(" Our rtc was just sync'd and the time is: "); Serial.println(timeNow); return(true); } else { Serial.println(" No wifi to check nist time with.");return(false); } } // end of function: nistTime String twoDigits(int digits){ // utility function for digital clock display: prints leading 0 if(digits < 10) { String zeroPaded = '0'+String(digits); return zeroPaded; } else { return String(digits); } } // end function twoDigits void oled(){ tNow = time(nullptr); // store the current time in 'tNow'. epoch seconds String timeNow = String(hourFormat12(tNow))+":"+twoDigits(minute(tNow))+":"+twoDigits(second(tNow)); display.setFont(ArialMT_Plain_16); // size 16 works ok if no decending char like "g" or all caps. display.setTextAlignment(TEXT_ALIGN_LEFT); display.drawString(0, 0, timeNow); if(WiFi.status() == WL_CONNECTED) {SetConnectionLEDOn();} else{SetConnectionLEDOff();} long rssi = WiFi.RSSI(); String signalStrength = String(rssi)+"dbm"; display.setTextAlignment(TEXT_ALIGN_RIGHT); display.drawString(128, 0, signalStrength); IPAddress ip = WiFi.localIP(); String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]); // ip address display.setFont(ArialMT_Plain_10); display.drawString(128, 16, ipStr); // ip address display.setTextAlignment(TEXT_ALIGN_LEFT); display.drawString(0,16, String("tpd ") + String(tpd)); display.drawString( 0,26, String("start in ") + String((sleepBtwnTurns - (unsigned long)(millis() - previousMillis))/1000) ); display.setTextAlignment(TEXT_ALIGN_RIGHT); display.drawString( 128,26, String(rot*2) + String(" turns/grp") ); display.drawString( 128,36, "v"+String(myVersionNumber) ); // v1.17.1.4 to 4th line display.setTextAlignment(TEXT_ALIGN_LEFT); display.setFont(ArialMT_Plain_10); display.drawString(0, 54, String("ccw")); display.drawString(30, 54, String(rcntCCW)); display.setTextAlignment(TEXT_ALIGN_RIGHT); display.drawString(105, 54, String(rcntCW)); display.drawString(128, 54, String("cw")); } // end function oled void dstSet() { // check and set the dst flag when needed tNow = time(nullptr); // store the current time in 'tNow'. epoch seconds int y = year(tNow) - 2000; // Get year from RTC and subtract 2000 int x = (y + y/4 + 2) % 7; // remainder will identify which day of month // is Sunday by subtracting x from the one // or two week window. First two weeks for March // and first week for November // need to set dst = 0 above if(month(tNow) == 3 && day(tNow) == (14 - x) && hour(tNow) == 2 && dst==0){ // *********** Test DST: BEGINS on 2nd Sunday of March @ 2:00 AM ********* setTime( tNow + (60*60*1000) ); // advance clock one hour in ms dst = 1; } if(month(tNow) == 3 && day(tNow) > (14 - x) || month(tNow) > 3){ // Daylight Savings Time is TRUE on powerup dst = 1; } if(month(tNow) == 11 && day(tNow) == (7 - x) && hour(tNow) == 2 && dst==1){ // ************* Test DST: ENDS on 1st Sunday of Nov @ 2:00 AM ************ setTime( tNow - (60*60*1000) ); // setback clock one hour in ms dst = 0; } if(month(tNow) == 11 && day(tNow) > (7 - x) || month(tNow) > 11 || month(tNow) < 3){ // daylight savings time is FALSE on powerup dst = 0; } } // end function to check for and set the dst flag. void wifiUP(String wifiStatus){ // can't do it out of setup ie pass setup a string. SetConnectionLEDOff(); // make sure we start in off as we haven't logged into wifi yet. SetActionLEDOn(); // show we are in setup or active. WiFi.disconnect(); // 1st time or on a retry, we disconnect so we can begin again. delay(1000); display.clear(); display.setFont(ArialMT_Plain_10); display.setTextAlignment(TEXT_ALIGN_LEFT); display.drawString(0, 3, "ssid: "+String(ssid)+"\n"+wifiStatus+" connecting:"); display.display(); // Display it on the screen Serial.println(); Serial.print(wifiStatus); Serial.print("\nconnecting to "); Serial.println(ssid); String wifiStatusCat = ""; // marching ssid connect status results. WiFi.begin(ssid, password); m = 0; // local counter for connect tries. while ( (WiFi.status() != WL_CONNECTED) && (m<15) ) { // try 16 times then give up. wifiStatusCat += String(WiFi.status()); display.drawStringMaxWidth(0, 29, 128, wifiStatusCat); // wraps text display.display(); // Display it on the screen Serial.print(WiFi.status()); m++; delay(1000); } if(WiFi.status() == WL_CONNECTED) { IPAddress ip = WiFi.localIP(); String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]); // ip address display.drawString(0, 54, "connected! "+ipStr); display.display(); // Display it on the screen SetConnectionLEDOn(); Serial.println("WiFi connected"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); delay(1000);} else{ SetConnectionLEDOff(); Serial.println(""); Serial.println("NOT connected"); } SetActionLEDOff(); // show we are done. } // end function: wifiUP // change log // $Log: stepper_winder.ino,v $ // Revision 1.17.1.4 2018/06/08 18:34:42 me // added current version to be displayed on oled. // // Revision 1.17.1.3 2018/06/08 17:39:40 me // same as v 1.21 trunk. // // Revision 1.17.1.2 2018/06/08 16:11:51 me // works. No switches. Cleaned up serial status output. // // Revision 1.17.1.1 2018/06/08 15:38:37 me // works. // this branch to look into adding switches. // |
top level subjects: |
Page last modified on June 12, 2018, at 07:17 PM |