/Users/Bilsma/Documents/Arduino/StepperWebServer/StepperWebServer.ino: In function 'void setup()':
StepperWebServer:75: error: 'blink' was not declared in this scope
blink();
^
/Users/Bilsma/Documents/Arduino/StepperWebServer/StepperWebServer.ino: In function 'void loop()':
StepperWebServer:108: error: 'blink' was not declared in this scope
blink();
^
StepperWebServer:112: error: 'getValue' was not declared in this scope
int rpm = getValue(req);
^
StepperWebServer:122: error: 'getValue' was not declared in this scope
int steps = getValue(req);
^
StepperWebServer:143: error: 'printUsage' was not declared in this scope
respMsg = printUsage();
^
exit status 1
'blink' was not declared in this scope
This report would have more information with
"Show verbose output during compilation"
enabled in File > Preferences.
Here is the code:
#include <ESP8266WiFi.h>
#include <Stepper.h>
// -- USER EDIT --
const char* ssid = "mywifi"; // YOUR WIFI SSID
const char* password = "mypassword"; // YOUR WIFI PASSWORD
// change this to your motor if not NEMA-17 200 step
#define STEPS 200 // Max steps for one revolution
#define RPM 60 // Max RPM
#define DELAY 1 // Delay to allow Wifi to work
// -- END --
int STBY = 5; // GPIO 5 TB6612 Standby
int LED = 0; // GPIO 0 (built-in LED)
// GPIO Pins for Motor Driver board
Stepper stepper(STEPS, 16, 14, 12, 13);
// Create an instance of the server
// specify the port to listen on as an argument
WiFiServer server(80);
void setup() {
Serial.begin(115200);
delay(10);
// prepare onboard LED
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH);
// prepare STBY GPIO and turn on Motors
pinMode(STBY, OUTPUT);
digitalWrite(STBY, HIGH);
// Set default speed to Max (doesn't move motor)
stepper.setSpeed(RPM);
// Connect to WiFi network
Serial.println();
Serial.println();
Serial.print("STEPPER: Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Start the server
server.begin();
Serial.println("Server started");
// Print the IP address
Serial.println(WiFi.localIP());
// Blink onboard LED to signify its connected
blink();
blink();
blink();
blink();
}
void loop() {
// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
return;
}
String respMsg = ""; // HTTP Response Message
// Wait until the client sends some data
Serial.println("new client");
while(!client.available()){
delay(1);
}
// Read the first line of the request
String req = client.readStringUntil('\r');
Serial.println(req);
client.flush();
// Match the request
if (req.indexOf("/stepper/stop") != -1) {
digitalWrite(STBY, LOW);
respMsg = "OK: MOTORS OFF";
}
else if (req.indexOf("/stepper/start") != -1) {
digitalWrite(STBY, HIGH);
blink();
respMsg = "OK: MOTORS ON";
}
else if (req.indexOf("/stepper/rpm") != -1) {
int rpm = getValue(req);
if ((rpm < 1) || (rpm > RPM)) {
respMsg = "ERROR: rpm out of range 1 to "+ String(RPM);
} else {
stepper.setSpeed(rpm);
respMsg = "OK: RPM = "+String(rpm);
}
}
// This is just a simplistic method of handling + or - number steps...
else if (req.indexOf("/stepper/steps") != -1) {
int steps = getValue(req);
if ((steps == 0) || (steps < 0 - STEPS) || ( steps > STEPS )) {
respMsg = "ERROR: steps out of range ";
} else {
digitalWrite(STBY, HIGH); // Make sure motor is on
respMsg = "OK: STEPS = "+String(steps);
delay(DELAY);
if ( steps > 0) { // Forward
for (int i=0;i<steps;i++) { // This loop is needed to allow Wifi to not be blocked by step
stepper.step(1);
delay(DELAY);
}
} else { // Reverse
for (int i=0;i>steps;i--) { // This loop is needed to allow Wifi to not be blocked by step
stepper.step(-1);
delay(DELAY);
}
}
}
}
else {
respMsg = printUsage();
}
client.flush();
// Prepare the response
String s = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n";
if (respMsg.length() > 0)
s += respMsg;
else
s += "OK";
s += "\n";
// Send the response to the client
client.print(s);
delay(1);
Serial.println("Client disconnected");
// The client will actually be disconnected
// when the function returns and 'client' object is detroyed
}
int getValue(String req) {
int val_start = req.indexOf('?');
int val_end = req.indexOf(' ', val_start + 1);
if (val_start == -1 || val_end == -1) {
Serial.print("Invalid request: ");
Serial.println(req);
return(0);
}
req = req.substring(val_start + 1, val_end);
Serial.print("Request: ");
Serial.println(req);
return(req.toInt());
}
String printUsage() {
// Prepare the usage response
String s = "Stepper usage:\n";
s += "http://{ip_address}/stepper/stop\n";
s += "http://{ip_address}/stepper/start\n";
s += "http://{ip_address}/stepper/rpm?[1 to " + String(RPM) + "]\n";
s += "http://{ip_address}/stepper/steps?[-" + String(STEPS) + " to " + String(STEPS) +"]\n";
return(s);
}
void blink() {
digitalWrite(LED, LOW);
delay(100);
digitalWrite(LED, HIGH);
delay(100);
}
I got it working after moving blink(), printUsage() and getValue() functions from the bottom of the sketch to just above the setup() function. I am just learning all this and want to understand what is going on here. From what I understand the code looks good and should work and what I did to fix it is not ideal.
Will anyone try and explain what is going on here.
PaulS:
What version of the IDE are you using? I compiled your code, as-posted, using 1.0.5 with no issues.
The latest 1.6.6
I know the error states this and I am not sure if this has anything to do with it or not, but I would like to point out I am using the "Adafruit HUZZAH ESP8266" board.
Ordinarily, in C and C++ code you must declare all functions above where they are used. The declaration can be the full function code or it can be just a 'forward declaration' which only names the function and the types of its arguments.
The normal Arduino IDE will insert its own forward declarations so you don't have to. Maybe something in the add-on has broken that feature? If it works with forward declarations, then keep doing it that way. It's a good habit to get into, in case you ever program something that's not Arduino.
MorganS:
Ordinarily, in C and C++ code you must declare all functions above where they are used. The declaration can be the full function code or it can be just a 'forward declaration' which only names the function and the types of its arguments.
The normal Arduino IDE will insert its own forward declarations so you don't have to. Maybe something in the add-on has broken that feature? If it works with forward declarations, then keep doing it that way. It's a good habit to get into, in case you ever program something that's not Arduino.
Hi Morgans,
Just so I am clear when I write a sketch for the Arduino I should create my functions before they are used so with me moving these functions where I did is actually good practice?
While I was researching this issue it appeared the sketches i looked at had the functions near the end like this sketch.
You mentioned that there maybe an add-on to the arduino IDE that may not be creating the forward declarations any idea what this add-on may be called or what verbiage I can use to search more on this issue? As you mentioned it may be good practice to declare these functions before used it appears that there are other that do not do this and it is kind of a pain to make this modification before I can compile other example code.
When I used to code in NEAT/3 everything had to be declared before it was used. It was a single-pass compiler, and if it didn't know about a function or variable on the first (and only) pass, then you got an error.
Also, there were no function prototypes to work around this problem by pre-declaring functions.
Thus you put the "main" code at the very end of your source file. Just before that was the functions that the main code would call. And so on, with the lowest-level functions at the start of the file.
It was good (and indeed required) practice, and also you knew therefore how to read the code. Go to the end, that is where it starts. Start looking backwards for the major functions etc.
Positionally you always knew where a function you were calling must be defined: prior to where it was called.
By "add on" I meant "Whatever Adafruit did to make the Arduino IDE work with their board." It's not a standard Arduino board that's supported by the IDE straight out of the box.
I would not expect that a simple board definition file would do this, but I haven't looked at what is required to make it work on that particular board.
My advice is to learn about function prototypes. Use that instead of reorganizing code.
Make a new tab in the IDE, call it foo.cpp. Put this in it:
#include <Arduino.h>
int bar ()
{
foo (42); // <--------- the compiler does not know about 'foo' here
}
int foo (int x)
{
Serial.println ("In foo");
}
That gives a compiler error:
foo.cpp: In function 'int bar()':
foo.cpp:4: error: 'foo' was not declared in this scope
foo (42);
^
'foo' was not declared in this scope
Two solutions
1. Change the order so that foo is declared before it is used:
#include <Arduino.h>
int foo (int x)
{
Serial.println ("In foo");
}
int bar ()
{
foo (42);
}
That compiles OK, because by the time foo is called, the compiler knows what sort of function it is (because it has already encountered it).
2. Make a function prototype for foo:
#include <Arduino.h>
int foo (int x); // prototype
int bar ()
{
foo (42);
}
int foo (int x)
{
Serial.println ("In foo");
}
This prototype tells the compiler (declares to the compiler) that there is, eventually, going to be a function called foo, that takes an int argument, and returns an int.
Later on we define what foo actually does.
That also compiles OK.
The Arduino IDE automatically tries to generate prototypes for you when it sees a function definition (by doing a pre-pass of the source file) to save you knowing this.
Wow Nick Thanks for taking the time to spell that out for me.
Can someone explain why the above code in the OP compiles fine with the IDE 1.6.5 but fails in 1.6.6?
Is the problem with the IDE? Or is there an issue with the Adafruit HUZZAH ESP8266 add-on not talking correctly to the 1.6.6 version of the IDE? or both?