New version with demo programs for the CodeRacer

This commit is contained in:
jglueck 2020-08-28 09:53:40 +02:00
parent c69acef5ef
commit ebb01e2964
6 changed files with 358 additions and 93 deletions

View File

@ -3,7 +3,6 @@
using namespace std;
static void global_stop_driving();
static void _count_steps_left();
static void _count_steps_right();
@ -17,7 +16,7 @@ static volatile float timebeforeleft= 0;
static volatile float timebeforeright= 0;
static volatile float timeafterleft= 0;
static volatile float timeafterright= 0;
static volatile bool obstacle_stop= true;
static volatile bool obstacle_stop= false;
static volatile bool obstacle_left_side= false;
static volatile bool obstacle_right_side= false;
static volatile bool coderracer_activ = false;
@ -53,6 +52,10 @@ CodeRacerMKII::CodeRacerMKII()
_led_right_pin = H_LED_RIGHT_PIN;
_led_blue_pin = H_LED_BLUE_PIN;
_led_white_pin = H_LED_WHITE_PIN;
_switch_1 = H_SWITCH_1;
_switch_2 = H_SWITCH_2;
_switch_3 = H_SWITCH_3;
_switch_4= H_SWITCH_4;
}
/** @brief CodeRace constructor with pins.This will overwrite the default settings taken from the header file.
@ -75,6 +78,10 @@ CodeRacerMKII::CodeRacerMKII()
* @param led_right_pin Pin the led that signals right side direction is connected at
* @param led_blue_pin Pin the blue led is connected at
* @param led_white_pin Pin the white led is connected at
@param switch_1 Pin the switch titled '1' is connected at
@param switch_2 Pin the switch titled '2' is connected at
@param switch_3 Pin the switch titled '3' is connected at
@param switch_4 Pin the switch titled '4' is connected at
* @return nothing
*/
CodeRacerMKII::CodeRacerMKII(uint8_t button_pin_left , uint8_t button_pin_right, uint8_t servo_pin,
@ -82,8 +89,8 @@ CodeRacerMKII::CodeRacerMKII(uint8_t button_pin_left , uint8_t button_pin_right,
uint8_t us_trigger_pin, uint8_t us_echo_pin,
uint8_t drive_left_frwd_bkwrd_pin, uint8_t drive_left_enable_pin,
uint8_t drive_right_frwd_bkwrd_pin, uint8_t drive_right_enable_pin,
uint8_t led_frwd_pin, uint8_t led_stop_pin, uint8_t led_left_pin, uint8_t led_right_pin, uint8_t led_blue_pin, uint8_t led_white_pin
)
uint8_t led_frwd_pin, uint8_t led_stop_pin, uint8_t led_left_pin, uint8_t led_right_pin, uint8_t led_blue_pin, uint8_t led_white_pin, uint8_t switch_1,
uint8_t switch_2, uint8_t switch_3, uint8_t switch_4)
{
_button_pin_left = button_pin_left;
_button_pin_right = button_pin_right;
@ -104,7 +111,10 @@ CodeRacerMKII::CodeRacerMKII(uint8_t button_pin_left , uint8_t button_pin_right,
_led_right_pin = led_right_pin;
_led_blue_pin = led_blue_pin;
_led_white_pin= led_white_pin;
_switch_1= switch_1;
_switch_2= switch_2;
_switch_3= switch_3;
_switch_4= switch_4;
}
/** @brief Initialisation of all attributes and settings of the coderacer. Defaults are taken from the header file.
@ -168,10 +178,15 @@ void CodeRacerMKII::begin() {
// Infrared sensors
pinMode(_infrared_sensor_left, INPUT);
pinMode(_infrared_sensor_right, INPUT);
pinMode(_infrared_sensor_right, INPUT_PULLDOWN);
attachInterrupt(digitalPinToInterrupt(_infrared_sensor_left), _stop_obstacle_left, CHANGE);
attachInterrupt(digitalPinToInterrupt(_infrared_sensor_right), _stop_obstacle_right, CHANGE);
// Switches
pinMode(H_SWITCH_1, INPUT_PULLUP);
pinMode(H_SWITCH_1, INPUT_PULLUP);
pinMode(H_SWITCH_3, INPUT_PULLUP);
pinMode(H_SWITCH_4, INPUT_PULLUP);
// Left drive
@ -204,13 +219,14 @@ void CodeRacerMKII::begin() {
attachInterrupt(digitalPinToInterrupt(_button_pin_right), _set_button_state_right, FALLING);
// Random
randomSeed(analogRead(0));
//randomSeed(analogRead(0));
//fun stuff
coderacer_fun_enabled = true;
servo_set_to_center();
//the Debug string for webserver
}
@ -229,10 +245,11 @@ void CodeRacerMKII::begin() {
*/
void CodeRacerMKII::stop_driving() {
_servo_sweep = false;
_drive = false;
global_stop_driving();
//set_drives_stop_left_right();
//set_leds(LEDOFF, LEDOFF, LEDON, LEDOFF, LEDOFF, LEDOFF);
_drive=false;
set_drives_stop_left_right();
wifi_printf("Stopped.");
set_leds(LEDOFF, LEDOFF, LEDON, LEDOFF, LEDOFF, LEDOFF);
set_leds_all_off();
}
/** @brief Sets the speed and the directions of both drives so that it will move forward.
@ -350,7 +367,7 @@ void CodeRacerMKII::turn_left(unsigned long turn_for_ms, uint8_t left_speed, uin
_turn_left_for_ms = turn_for_ms;
wait_ms(_turn_left_for_ms);
// stop drives again
global_stop_driving();
stop_driving();
}
/** @brief Will turn the racer to the right for the internally stored time in ms and with the internally stored speed.
@ -394,7 +411,7 @@ void CodeRacerMKII::turn_right(unsigned long turn_for_ms, uint8_t left_speed, ui
_turn_right_for_ms = turn_for_ms;
wait_ms(_turn_right_for_ms);
// stop drives again
global_stop_driving();
stop_driving();
}
/** @brief Enables to stop the racer if during a distance measurement the measured distance is smaller then the internally stored minimal distance.
@ -412,7 +429,7 @@ void CodeRacerMKII::start_stop_at_min_distance() {
/** @brief Enables to stopp the racer if during a distance measurement the measured distance is smaller then the specified minimal distance.
*
* This is almos the same as described for start_stop_at_min_distance(). You can specify the distance in cm here - this value will be stored internally and used by start_stop_at_min_distance() next time.
* @param min_distance_cm the minimal disctance in cm
* @param min_distance_cm the minimal distance in cm
* @return nothing
*/
void CodeRacerMKII::start_stop_at_min_distance(unsigned long min_distance_cm) {
@ -465,17 +482,15 @@ bool CodeRacerMKII::start_stop() {
* @return debug_message
*/
String CodeRacerMKII::wifi_printf(){
return debug_message;
}
/** @brief Almost the same as wifi_printf(), but with a specified message to send to the webserver. can be used to send custom messages for debugging.
/** @brief Almost the same as wifi_printf(), but with a specified message to send to the webserver. Can be used to send custom messages for debugging.
* @param Content the message specified by user
* @return debug_message
*/
String CodeRacerMKII::wifi_printf(String Content){
debug_message= Content;
return debug_message;
}
/** @} */ // end of group higherlevelmeths
/** @defgroup higherlevelgetters Getters and setters
@ -579,6 +594,9 @@ unsigned int CodeRacerMKII::show_right_stepcounter(){
return right_step_counter;
}
/* Experimental stuff. Routines to calculate the CodeRacer's current veliocity- measured in ticks/s... but the parameters timeafterleft, timebeforeleft etc. use millis()-
so the code crashes if this is done during the interrupt rountines.
unsigned long CodeRacerMKII::show_left_time_of_last_tick(){
return timeafterleft;
}
@ -602,6 +620,7 @@ void CodeRacerMKII::set_left_start_time(){
void CodeRacerMKII::set_right_start_time(){
timebeforeright=0;
}
*/
/** @} */ // end of group higherlevelgetters
/** @} */ // end of group higherlevel
@ -631,7 +650,7 @@ void CodeRacerMKII::look_around()
}
}
/** @brief Fun stuff - you know Knightrider...
/** @brief Fun stuff - you know Knight Rider...
* @return nothing
*/
void CodeRacerMKII::kitt()
@ -670,6 +689,36 @@ void CodeRacerMKII::kitt()
}
}
/** @brief Reads the four little switches and returns a value from 1-4, depending which of them is turned on.
* Only the first switch turned on is read.
* @return an integer from 1 to 4, representing the number of the switch currently active
*/
int CodeRacerMKII::switch_check()
{
int generalMode=0;
if(digitalRead(_switch_1)==LOW)
{
generalMode=1;
return generalMode;
}
if(digitalRead(_switch_2)== LOW)
{
generalMode=2;
return generalMode;
}
if(digitalRead(_switch_3)==LOW)
{
generalMode=3;
return generalMode;
}
if(digitalRead(_switch_4)==LOW)
{
generalMode=4;
return generalMode;
}
return generalMode;
}
/** @} */ // end of group lowerlevelfun
@ -924,7 +973,7 @@ unsigned long CodeRacerMKII::_servo_set_position(uint8_t position)
}
_servo->write(_position);
// wait minimal delay to avoid code collaps
delay(SERVO_SET_1TICK_POSITION_DELAY_MS);
wait_ms(SERVO_SET_1TICK_POSITION_DELAY_MS);
absdiff = abs(_servo_position - _position);
if (absdiff > 1) {
_servo_position_eta_in_ms = absdiff * SERVO_SET_1TICK_POSITION_DELAY_MS;
@ -1216,7 +1265,7 @@ void CodeRacerMKII::drives_settings(uint8_t drive_left_speed, uint8_t drive_righ
* @return nothing
*/
void CodeRacerMKII::Reset_Stats(){
global_stop_driving();
stop_driving();
left_step_counter=0;
right_step_counter=0;
driven_distance=0;
@ -1225,6 +1274,11 @@ void CodeRacerMKII::Reset_Stats(){
wifi_printf("Resetted stats.");
}
void CodeRacerMKII::set_drives_stop_left_right() {
set_drive_left_state(DRIVESTOP);
set_drive_right_state(DRIVESTOP);
}
/** @brief Sets both of the drives to a specified drivestate (DRIVESTOP, DRIVEFRWD, DRIVEBACK)
* @param stateleft drivestate to set for the left side drive
* @param stateright drivestate to set for the right side drive
@ -1270,7 +1324,7 @@ void CodeRacerMKII::set_drive_state(drivestate state, uint8_t frwdbackpin, uint8
break;
}
}
/** @brief enables or disables a syncronized halting if the method global_stop_driving() is used. if disabled, the left engine will continue running.
/** @brief enables or disables a syncronized halting if the method stop_driving() is used. if disabled, the left engine will continue running.
* @param state a boolean expression to enable or disable syncstop. this variable is set false by default.
* @return nothing
*/
@ -1551,12 +1605,21 @@ void CodeRacerMKII::set_leds_all_on() {
//*** ISRs ***
//**************************************
//IRAM_ATTR is used to load the code into DRAM and not to Flash to make it faster - required for ISRs
/** @brief this ISR is called each time the left button is pressed, and toggles the Racer between active and inactive mode.
* @return nothing
*/
void IRAM_ATTR CodeRacerMKII::_set_button_state_left() {
if ((millis() - left_button_last_pressed_at_ms) > BUTTON_BOUNCING_TIME_MS) {
left_button_last_pressed_at_ms = millis(); // simplest debouncing - just wait ;-)
coderracer_activ = !coderracer_activ;
}
}
/** @brief this ISR is called each time the right button is pressed and increments a counter variable for it. THis variable has no use
* at the current moment, so feel free to use it in your main.
* @return nothing
*/
void IRAM_ATTR CodeRacerMKII::_set_button_state_right() {
if ((millis() - right_button_last_pressed_at_ms) > BUTTON_BOUNCING_TIME_MS) {
right_button_last_pressed_at_ms = millis();
@ -1565,31 +1628,8 @@ void IRAM_ATTR CodeRacerMKII::_set_button_state_right() {
}
}
/** @brief basically the same as stop_driving(), but is required for all routines attached to an interrupt which can't call stop_driving()
* @return nothing
*/
static void IRAM_ATTR global_stop_driving(){
ledcWrite(DRIVE_PWM_RIGHT_CHANNEL, 0);
if(true == syncstop)
{
ledcWrite(DRIVE_PWM_LEFT_CHANNEL, 0);
}
debug_message+="Stopped.";
digitalWrite(H_LED_RIGHT_PIN, LOW);
digitalWrite(H_LED_LEFT_PIN, LOW);
digitalWrite(H_LED_STOP_PIN, HIGH);
digitalWrite(H_LED_FRWD_PIN, LOW);
digitalWrite(H_LED_BLUE_PIN, LOW);
digitalWrite(H_LED_WHITE_PIN, LOW);
_drive= false;
digitalWrite(H_LED_RIGHT_PIN, LOW);
digitalWrite(H_LED_LEFT_PIN, LOW);
digitalWrite(H_LED_STOP_PIN, LOW);
digitalWrite(H_LED_FRWD_PIN, LOW);
digitalWrite(H_LED_BLUE_PIN, LOW);
digitalWrite(H_LED_WHITE_PIN, LOW);
}
/** @brief this routine is called each time the left PE barrier changes its state. it increments (and by that counts) the ticks driven by the left wheel and is also instructed to stop the racer if the stopcount set by drive_ticks() is reached using the global_stop_driving() routine
/** @brief this routine is called each time the left PE barrier changes its state. it increments (and by that counts) the ticks driven by the left wheel and is also instructed to stop the racer if the stopcount set by drive_ticks() is reached using the stop_driving() routine
* @return nothing
*/
static void IRAM_ATTR _count_steps_left() {
@ -1598,13 +1638,13 @@ static void IRAM_ATTR _count_steps_left() {
left_step_counter++;
if (left_step_counter==left_step_stopcount)
{
global_stop_driving();
Coderacer.stop_driving();
left_step_stopcount= 0;
right_step_stopcount=0;
}
}
/** @brief this routine is called each time the left PE barrier changes its state. it increments (and by that counts) the ticks driven by the right wheel and is also instructed to stop the racer if the stopcount set by drive_ticks() is reached using the global_stop_driving() routine
/** @brief this routine is called each time the left PE barrier changes its state. it increments (and by that counts) the ticks driven by the right wheel and is also instructed to stop the racer if the stopcount set by drive_ticks() is reached using the stop_driving() routine
* @return nothing
*/
static void IRAM_ATTR _count_steps_right() {
@ -1614,34 +1654,33 @@ static void IRAM_ATTR _count_steps_right() {
right_step_counter++;
if (right_step_counter==right_step_stopcount)
{
global_stop_driving();
Coderacer.stop_driving();
left_step_stopcount=0;
right_step_stopcount=0;
}
}
/** @brief this routine is called each time the left infrared sensor changes its state. it sets the boolean variable obstacle_left_side to true/false and, if obstacle_stop is enabled, also stops the racer using global_stop_driving()
/** @brief this routine is called each time the left infrared sensor changes its state. it sets the boolean variable obstacle_left_side to true/false and, if obstacle_stop is enabled, also stops the racer using stop_driving()
* @return nothing
*/
void IRAM_ATTR CodeRacerMKII::_stop_obstacle_left(){
if(LOW== digitalRead(H_INFRARED_SENSOR_LEFT)){
if(HIGH== digitalRead(H_INFRARED_SENSOR_LEFT)){
if(true==obstacle_stop){
global_stop_driving();
Coderacer.stop_driving();
}
obstacle_left_side=true;
}
else obstacle_left_side= false;
}
/** @brief this routine is called each time the left infrared sensor changes its state. it sets the boolean variable obstacle_left_side to true/false and, if obstacle_stop is enabled, also stops the racer using global_stop_driving()
/** @brief this routine is called each time the left infrared sensor changes its state. it sets the boolean variable obstacle_left_side to true/false and, if obstacle_stop is enabled, also stops the racer using stop_driving()
* @return nothing
*/
void IRAM_ATTR CodeRacerMKII::_stop_obstacle_right(){
if(HIGH== digitalRead(H_INFRARED_SENSOR_RIGHT)){
if(1==obstacle_stop){
global_stop_driving();
Coderacer.stop_driving();
}
obstacle_right_side=true;
}

View File

@ -42,7 +42,7 @@
#define H_LEFT_BARRIER_PIN 34
#define H_RIGHT_BARRIER_PIN 35
#define TURN 20
#define WHEEL_DIAMETER_MM 70
#define WHEEL_DIAMETER_MM 70 // Other wheel measurements can be defined here
#define SCOPE_OF_WHEEL PI*WHEEL_DIAMETER_MM
#define DISTANCE_PER_TICK_MM SCOPE_OF_WHEEL/TURN
#define DISTANCE_BETWEEN_WHEELS_MM 112
@ -54,6 +54,12 @@
#define H_INFRARED_SENSOR_LEFT 36
#define H_INFRARED_SENSOR_RIGHT 39
//----- Switches -----
#define H_SWITCH_1 4
#define H_SWITCH_2 0
#define H_SWITCH_3 2
#define H_SWITCH_4 15
//----- Ultrasonic sensor -----
#define H_US_TRIG_PIN 21
#define H_US_ECHO_PIN 17
@ -132,6 +138,10 @@ class CodeRacerMKII {
uint8_t _led_right_pin;
uint8_t _led_blue_pin;
uint8_t _led_white_pin;
uint8_t _switch_1;
uint8_t _switch_2;
uint8_t _switch_3;
uint8_t _switch_4;
//servo variables
int8_t _servo_sweep_step;
@ -194,7 +204,8 @@ class CodeRacerMKII {
uint8_t us_trigger_pin, uint8_t us_echo_pin,
uint8_t drive_left_frwd_bkwrd_pin, uint8_t drive_left_enable_pin,
uint8_t drive_right_frwd_bkwrd_pin, uint8_t drive_right_enable_pin,
uint8_t led_frwd_pin, uint8_t led_stop_pin, uint8_t led_left_pin, uint8_t led_right_pin, uint8_t led_blue_pin, uint8_t led_white_pin);
uint8_t led_frwd_pin, uint8_t led_stop_pin, uint8_t led_left_pin, uint8_t led_right_pin, uint8_t led_blue_pin, uint8_t led_white_pin, uint8_t switch_1,
uint8_t switch_2, uint8_t switch_3, uint8_t switch_4);
void set_inactive();
void set_active();
@ -277,6 +288,7 @@ class CodeRacerMKII {
void drives_settings(uint8_t drive_left_speed, uint8_t drive_right_speed, unsigned long turn_left_ms, unsigned long turn_right_ms);
void Reset_Stats();
void set_drives_states_left_right(drivestate stateleft, drivestate stateright);
void set_drives_stop_left_right();
void set_drive_left_state(drivestate state);
void set_drive_right_state(drivestate state);
void set_syncstop(bool state);
@ -323,6 +335,7 @@ class CodeRacerMKII {
// just for fun
void kitt();
void look_around();
int switch_check();

View File

@ -1,4 +1,5 @@
#include "Webserver.h"
/** @brief Constructor for the webserver
* @param ssid Network SSID
* @param password password of the network the CodeRacer is connected to
@ -16,8 +17,8 @@ void notFound(AsyncWebServerRequest *request) {
}
/** @brief The bread-and-butter-routine of the webserver. Connects to a Wifi network with the SSID and password defined by the constructor. Contains various routines
* telling the server what to do if a GET request comes in by the client. You can add events using server.on() here to call routines of the CodeRacer.
*/
* telling the server what to do if a GET request comes in by the client.
*/
void Codeserver::Run(){
//Connecting to Wifi network
Serial.print("Connecting to");
@ -28,19 +29,31 @@ void Codeserver::Run(){
Serial.print(".");
}
Serial.println("");
Coderacer.wifi_printf("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// Definition for events triggered by the GET request of the client
// Definition for events triggered by the GET request of the client.You can add events using server.on() here to call routines of the CodeRacer-
// if you define the GET request correctly in the HTML code.
server.on("/", HTTP_GET, [] (AsyncWebServerRequest *request){
String message;
request->send(200, "text/html", String(indexHTML));
Serial.printf("Webpage sent\n");
});
server.on("/SetInactive", HTTP_GET, [] (AsyncWebServerRequest *request){
Coderacer.set_inactive();
request->send(200, "text/plain", "Hello world");
//this text is returned with the AJAX GET- request, but not shown on the website. Needed for appropiate handling of the request though.
});
server.on("/SetActive", HTTP_GET, [] (AsyncWebServerRequest *request){
Coderacer.set_active();
request->send(200, "text/plain", "Hello world");
});
server.on("/DriveForward", HTTP_GET, [] (AsyncWebServerRequest *request){
Coderacer.drive_forward();
request->send(200, "text/plain", "Hello world");
@ -57,12 +70,12 @@ void Codeserver::Run(){
});
server.on("/TurnLeft", HTTP_GET, [] (AsyncWebServerRequest *request){
Coderacer.turn_left();
Coderacer.turn_degree(-90);
request->send(200, "text/plain", "Hello, world");
});
server.on("/TurnRight", HTTP_GET, [] (AsyncWebServerRequest *request){
Coderacer.turn_right();
Coderacer.turn_degree(90);
request->send(200, "text/plain", "Hello, world");
});

View File

@ -1,13 +1,13 @@
// Necessary to avoid multiple includes of this header
#ifndef __CodeRacer_WEBSERVER_H__
#ifndef __CodeRacer_WEBSERVER_H__ // Necessary to avoid multiple includes of this header
#define __CodeRacer_WEBSERVER_H__
#include "CodeRacer_MKII.h"
#include <AsyncTCP.h>
#include <AsyncTCP.h> // external library for asynchronous webserver for ESP32
#include <ESPAsyncWebServer.h>
// This is a char array containing the html code for the website. It is sent ONCE when the webserver first initializes.
// The script contains various routines telling what the AJAX object should do and when.
// It is strongly advised NOT to change the html text, unless you know exactly what you're doing!
// In line 21, you should change your IP adress so the Webserver can work properly
const char indexHTML[] PROGMEM = R"=====(
<!DOCTYPE html>
@ -30,10 +30,6 @@ const char indexHTML[] PROGMEM = R"=====(
function aktualisieren()
{
var state=myAjax.readyState;
document.getElementById('AJAXstate').innerHTML= "AJAX state: " +state;
var statustext=myAjax.statusText;
document.getElementById('AJAXstatus').innerHTML= "Status text: " +statustext;
myAjax.open("GET", Url+"Values", true);
myAjax.send();
}
@ -107,9 +103,11 @@ const char indexHTML[] PROGMEM = R"=====(
<h1>Welcome to the CodeRacer Webserver!</h1>
<p><button class="button" onclick="httpGet('DriveForward')">Drive Forward</button>
<button class="button" onclick="httpGet('DriveBackward')">Drive Backward</button>
<button class="button" onclick="httpGet('StopDriving')">Stop Driving</button>
<button class="button" onclick="httpGet('TurnLeft')">Turn Left</button>
<button class="button" onclick="httpGet('TurnRight')">Turn Right</button>
<button class="button3" onclick="httpGet('StopDriving')">Stop Driving</button>
<button class="button" onclick="httpGet('SetActive')">Set Active</button>
<button class="button3" onclick="httpGet('SetInactive')">Set Inactive</button>
<p>
<label for="speed">Set new Speed</label>
<input id="speed" type="text" placeholder="Enter value (0-255)" />

View File

@ -0,0 +1,223 @@
// Example Code of a CodeRacer sketch with implementation of a webserver
#include "CodeRacer_MKII.h"
#include "Webserver.h"
CodeRacerMKII Coderacer; // Inizialization of your CodeRacer
AsyncWebServer server(80); // IMPORTANT definition of the asynchronous Web server, including port number
int Distance;
int DemoMode=0;
int maximum= 0;
int Array[160];
int Degrees[160];
int location= 0; // Some numbers we need for later...
Codeserver Test((char*)"coderacer_ap", (char*)"007coderacer"); // Creation of the webserver. enter your network's SSID and password here
void setup()
{
Coderacer.begin();
Coderacer.servo_sweep_left_pos=120; // Just a few adjustments to the servo_sweep parameters- that way, the servo sweeps more narrowly
Coderacer.servo_sweep_right_pos= 60;
/* One problem we came across during the testing of the Coderacer was, that the two engines don't run equally fast- meaning that even with
identical speed (let's say 130, 130), the Racer will slowly pull to one side on longer distances. To adjust this issue, all you can do for now is test
which engine is more powerful- and adjust your speed for the left and right side drives accordingly. */
Coderacer.speed_settings(140, 130);
Serial.begin(115200);
Test.Run(); // Calls the Run() routine, which manages everything the webserver needs to work
Coderacer.wifi_printf("Activate a switch to choose a Demonstration program.");
wait_ms(1000);
/*the IP adress of the server is given out on the Serial monitor. It is currently connected to the CodeRacer we used for testing and programming this sample code.
If the IP adress of YOUR CodeRacer differs from the one specified in Webserver.cpp, you have to change the following part of the HTML char array:
var Url ="http://192.168.1.146/"; --> var Url ="your_IP_adress"; */
}
void loop()
/* the loop contains four demonstration example codes, seperated by switch/ case which are supposed to give you the idea of the
CodeRacer routines, what they do, how you can use them and what you need to consider before doing so. By turning on one of the switches, you select one of the demos.
Activate the CodeRacer by pressing the left button, and watch the CodeRacer doing (hopefully) what it is advised to. Don't hesitate to watch the Webserver as well,
instructions on how to get it running are shown and executed above. */
{
DemoMode= Coderacer.switch_check();
switch (DemoMode)
{
case 0:
{
Coderacer.kitt(); // This is just some fun stuff happening while no program has been selected... feel free to edit it out :)
break;
}
case 1:
/* a Demo featuring: measuring the distance, driving forward until it falls below a certain value, then driving back
for a small amount of time and turning 90 degrees to the right. NOTE: if you want to print out debug message on the Webserver,
build in a certain delay time so the AJAX protocoll can process the message (otherwise it won't get displayed). */
{
Coderacer.wifi_printf("Selected: Demo 1, activate your CodeRacer to start");
Coderacer.set_leds_all_off();
wait_ms(5000);
while(Coderacer.is_active()) // If the left button is pressed, the CodeRacer becomes active and the loop starts
{
wait_ms(300);
Distance= Coderacer.usonic_measure_single_shot_cm();
while(Distance>25)
{
Distance=Coderacer.usonic_measure_single_shot_cm();
Coderacer.servo_sweep();
Coderacer.drive_forward();
// tells the CodeRacer to drive forward while sweeping the servo from left to right (the sweeping range is defined eariler in this code) and measure the distance
}
Coderacer.stop_driving();
Coderacer.servo_set_to_center();
wait_ms(500);
Coderacer.drive_backward_for_ms(500);
wait_ms(500);
Coderacer.wifi_printf("Drehung!"); //prints out a message on the webserver
wait_ms(500);
Coderacer.turn_degree(80); // Due to the inertia of the wheels, lower the degrees of the turn a bit- in this case, although 80 are stated, the Racer does an almost perfect 90 degree turn...
wait_ms(500);
}
break;
}
case 2:
/* a more "intelligent" way to tell the CodeRacer where to drive. Basically the idea is to let the CodeRacer drive forward until a certain distance is reached (as done before).
Then, the servo sweeps from left to right filling an array of distances, getting the index of the highest value and then turning a precise amount of degrees,
depending on that value. The scheme of the code is explained below*/
{
Coderacer.wifi_printf("Selected: Demo 2, activate your CodeRacer to start");
Coderacer.set_leds_all_off();
wait_ms(5000);
while(Coderacer.is_active())
{
Distance= Coderacer.usonic_measure_cm();
while (Distance>25) // Again a simple way to tell the Racer "drive until a distance of __ cm is reached"
{
Distance= Coderacer.usonic_measure_single_shot_cm();
Coderacer.servo_sweep();
Coderacer.drive_forward(210, 190);
}
Coderacer.stop_driving();
wait_ms(1000);
for(int i=0, k=10; i<160; i++, k++) // sweeps the servo from right to leftmost position and fills an array with the measured distances
{
Coderacer.servo_set_position_wait(k);
Array[i]=Coderacer.usonic_measure_single_shot_cm();
}
Coderacer.servo_set_to_center(); // Reset servo
wait_ms(200);
maximum= Array[0]; // Defines the maximum value of the array at the index 0
for (int c = 0; c < 160; c++) // Emitts the highest value of the distance- array. One flaw: only the first time this value shows up is saved.
{
if (Array[c] > maximum)
{
maximum = Array[c];
location = c;
}
}
for(int i=0, k=80; i<160; i++, k--) // Finally, create an array of degrees from 80 to -80 (representing the distance array from 0 to 160)
{
Degrees[i]= k;
}
Coderacer.turn_degree(Degrees[location]); // ...And turn the servo by the number of degrees roughly representing the biggest distance!
wait_ms(500);
}
break;
}
case 3:
/* a demo program featuring: an alternative way telling the CodeRacer to stop when a ceratin distance is reached. the Racer will drive around
happily, turning left and right until the specified value is measured. NOTE: it might occur that the Racer won't get to measure the stop distance
- if that is the case, just hold your hand in front of it so it breaks out of the while- loop ;) */
{
Coderacer.wifi_printf("Selected: Demo 3, activate your CodeRacer to start");
Coderacer.set_leds_all_off();
wait_ms(5000);
while(Coderacer.is_active())
{
Distance = Coderacer.usonic_measure_cm(); // measure the distance - at the position of the servo
Coderacer.start_stop_at_min_distance(20); // Select a distance- the CodeRacer will stop if the Usonic Sensor measures it
while(!Coderacer.stopped_at_min_distance()) // WHILE the CodeRacer hasn't stopped at the previous declared distance...
{
if(Distance > 50)
{
Coderacer.drive_forward();
Coderacer.servo_sweep();
}
else if(Distance > 40)
{
Coderacer.turn_right();
}
else if(Distance > 30)
{
Coderacer.turn_left();
}
else
{
Coderacer.drive_backward();
}
Distance = Coderacer.usonic_measure_cm();
// Measure the distance again- be careful with usonic_measure_cm(), as this method takes a while to complete. Calling it too fast will crash your Code.
}
Coderacer.wifi_printf("Stopped at minimal stopped distance selected by user!!");
wait_ms(2000);
Coderacer.set_inactive();
}
break;
}
case 4:
/* a demo program showing the scheme of displaying messages in the Webserver. After doing so, take a look at the dashboard on the website!
the racer will drive a specific amounts of ticks for the left and right wheel afterwards, you can check if that works correctly looking into
the table. NOTE: you might want to disable the CodeRacer from driving away- no stopping condition built in this time, so it might
bump into something while driving... just let the wheels turn freely and watch the dashboard... */
{
Coderacer.wifi_printf("Selected: Demo 4, activate CodeRacer to start");
Coderacer.set_leds_all_off();
wait_ms(5000);
while(Coderacer.is_active())
{
Coderacer.set_obstacle_stop(true);
Coderacer.wifi_printf("Welcome...");
wait_ms(1000);
// As previously mentioned, the website resfrehes internally, but only in an interval of 750ms
// So if you want your message to be properly displayed, you got to build in a delay using wait_ms...
Coderacer.wifi_printf("Using wifi_printf");
wait_ms(1000);
Coderacer.wifi_printf("You can display custom messages on the Webserver!");
wait_ms(1000);
Coderacer.wifi_printf("But you knew that already!");
wait_ms(1000);
Coderacer.wifi_printf("Dont forget to build in small waiting windows...");
wait_ms(1000);
Coderacer.wifi_printf("So your message is transmitted properly!");
wait_ms(1000);
Coderacer.wifi_printf("Also, check out the clear button!");
wait_ms(1000);
Coderacer.wifi_printf("Now, watch the stepcounters in the table!");
wait_ms(2000);
Coderacer.drive_ticks_left(200, true);
while (true== Coderacer.is_driving()){} // IMPORTANT! halts the Code while the Racer is driving its __ steps on each side.
wait_ms(3000);
Coderacer.Reset_Stats(); // Resets the stats of the Racer, including stepcounters and speed settings to default.
Coderacer.speed_settings(255, 245); // New Speed settings for both drives...
wait_ms(3000); // The delay is once again needed so the debug message of reset_stats() is properly displayed...
Coderacer.drive_ticks_right(200, true);
while (true== Coderacer.is_driving()){}
Coderacer.wifi_printf("End of demo 3!");
wait_ms(3000);
Coderacer.set_inactive();
}
break;
}
}
}

View File

@ -1,21 +0,0 @@
// Example Code of a CodeRacer sketch with implementation of a webserver
#include "CodeRacer_MKII.h"
#include "Webserver.h"
CodeRacerMKII Coderacer;
// IMPORTANT definition of the server port
AsyncWebServer server(80);
// Definition of the webserver. enter your network's SSID and password here
Codeserver Test((char*)"coderacer_ap", (char*)"007coderacer");
void setup() {
Coderacer.begin();
Serial.begin(115200);
// Calls the Run() routine, which manages everything the webserver needs to work
Test.Run();
}
void loop()
{
//Coderacer.speed_settings(255, 250);
}