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