So, i am going to be honest and tell you from the start that i don't have strong knowledge of c++, but i have a project that needs a little bit of c++ programming so i am here, asking for some help/guidance.
I have a microcontroller from Diligent, a chipkit Max32 and a Network Shield to be precise ! My project is to make a little program and a web page so i can open and close some LEDs. After i'm done with these things, i have to write a code to read some values from a potentiometer, but that is a solved problem.
After some research and several good hours of testing and failing, i managed to find 2 examples of working projects. 1 of them is for 1 LED, tested and working, but couldn't make it work properly for 4 LEDs. After some more research, i've found out that i need to use the FOR command. With a little bit of luck, i found and example of a code that uses this FOR command but doesn't work for my controller. With a little bit of modifications i managed to compile, but it doesn't work how it should.
Here is where i need professional help : I can read and understand most of the code, but because i'm not familiar with c++, i don't know what, how or why to modify in order to make this little project work.
I will post here the code, hope it will make some sense and at the end of the code i will specify what i need to know how to do or to modify.
Here is the code with the necesary info :
char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string
char req_index = 0; // index into HTTP_req buffer
unsigned char LED_state[3] = {0}; // stores the states of the LEDs, 1 bit per LED
void setup()
{
int i;
Serial.begin(9600); // for debugging
// pins 26 to 49 are outputs
for (i = 26; i <= 49; i++) {
pinMode(i, OUTPUT); // set pins as outputs
digitalWrite(i, LOW); // switch the output pins off
}
Ethernet.begin(mac, ip, gateway, subnet); // initialize Ethernet device
server.begin(); // start to listen for clients
}
void loop()
{
Client client = server.available(); // try to get client
if (client) { // got client?
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) { // client data available to read
char c = client.read(); // read 1 byte (character) from client
// limit the size of the stored received HTTP request
// buffer first part of HTTP request in HTTP_req array (string)
// leave last element in array as 0 to null terminate string (REQ_BUF_SZ - 1)
if (req_index < (REQ_BUF_SZ - 1)) {
HTTP_req[req_index] = c; // save HTTP request character
req_index++;
}
// last line of client request is blank and ends with \n
// respond to client only after last line received
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
// remainder of header follows below, depending on if
// web page or XML page is requested
// Ajax request - send XML file
if (StrContains(HTTP_req, "ajax_inputs")) {
// send rest of HTTP header
client.println("Content-Type: text/xml");
client.println("Connection: keep-alive");
client.println();
SetLEDs();
// send XML file containing input states
XML_response(client);
}
// display received HTTP request on serial port
//Serial.print(HTTP_req);
// reset buffer index and all buffer elements to 0
req_index = 0;
StrClear(HTTP_req, REQ_BUF_SZ);
break;
}
// every line of text received from the client ends with \r\n
if (c == '\n') {
// last character on line of received text
// starting new line with next character read
currentLineIsBlank = true;
}
else if (c != '\r') {
// a text character was received from client
currentLineIsBlank = false;
}
} // end if (client.available())
} // end while (client.connected())
delay(1); // give the web browser time to receive the data
client.stop(); // close the connection
} // end if (client)
}
// checks if received HTTP request is switching on/off LEDs
// also saves the state of the LEDs
void SetLEDs(void)
{
char str_on[12] = {0};
char str_off[12] = {0};
unsigned char i;
unsigned int j;
int LED_num = 1;
for (i = 0; i < 3; i++) {
for (j = 1; j <= 0x08; j <<= 1) {
sprintf(str_on, "LED%d=%d", LED_num, 1);
sprintf(str_off, "LED%d=%d", LED_num, 0);
if (StrContains(HTTP_req, str_on)) {
LED_state[i] |= (unsigned char)j; // save LED state
digitalWrite(LED_num + 25, HIGH);
Serial.println("ON");
}
else if (StrContains(HTTP_req, str_off)) {
LED_state[i] &= (unsigned char)(~j); // save LED state
digitalWrite(LED_num + 25, LOW);
}
LED_num++;
}
}
}
// send the XML file with analog values, switch status
// and LED status
void XML_response(Client cl)
{
unsigned char i;
unsigned int j;
cl.print("<?xml version = \"1.0\" ?>");
cl.print("<inputs>");
for (i = 0; i < 3; i++) {
for (j = 1; j <= 0x08; j <<= 1) {
cl.print("<LED>");
if ((unsigned char)LED_state[i] & j) {
cl.print("checked");
//Serial.println("ON");
}
else {
cl.print("unchecked");
}
cl.println("</LED>");
}
}
cl.print("</inputs>");
}
// sets every element of str to 0 (clears array)
void StrClear(char *str, char length)
{
for (int i = 0; i < length; i++) {
str[i] = 0;
}
}
// searches for the string sfind in the string str
// returns 1 if string found
// returns 0 if string not found
char StrContains(char *str, char *sfind)
{
char found = 0;
char index = 0;
char len;
len = strlen(str);
if (strlen(sfind) > len) {
return 0;
}
while (index < len) {
if (str[index] == sfind[found]) {
found++;
if (strlen(sfind) == found) {
return 1;
}
}
else {
found = 0;
}
index++;
}
return 0;
}
So ...First: i kinda understand this "for (i = 26; i <= 49; i++)", but i'm not sure how to modify it for the output pins 1 - 8. should i write "for (i=1; i <= 9; i++)" ?
Second: in the Void SetLEDs(void) section, that is what i need to understand how it works and how i can modify. I assume that the "(unsigned char)j" memorizes the state of the LED "On/Off" . And (unsigned char)~j ? what does that ~ do ?
Third: i don't understand what does "char StrContains" .
And last : the "void XML_response(Client cl)" is made for and index.htm stored on an SD card. My controller does not have and SD slot, so i'll have to make the checkboxes or buttons in html.
I am sorry for the very long post, but i'm in a little bit of a problem and because of my lack of c++ skills, it's getting difficult to finish this task. I appreciate any help/comment/critic. I really need to make this work or to find out a solution.
P.S. : The code doesn't belong to me, but you probably figured that out :D
P.S.2 : Sorry for my bad english
char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string
char req_index = 0; // index into HTTP_req buffer
unsignedchar LED_state[3] = {0}; // stores the states of the LEDs, 1 bit per LED
void setup()
{
int i;
Serial.begin(9600); // for debugging
// pins 26 to 49 are outputs
for (i = 26; i <= 49; i++) {
pinMode(i, OUTPUT); // set pins as outputs
digitalWrite(i, LOW); // switch the output pins off
}
Ethernet.begin(mac, ip, gateway, subnet); // initialize Ethernet device
server.begin(); // start to listen for clients
}
void loop()
{
Client client = server.available(); // try to get client
if (client) { // got client?
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) { // client data available to read
char c = client.read(); // read 1 byte (character) from client
// limit the size of the stored received HTTP request
// buffer first part of HTTP request in HTTP_req array (string)
// leave last element in array as 0 to null terminate string (REQ_BUF_SZ - 1)
if (req_index < (REQ_BUF_SZ - 1)) {
HTTP_req[req_index] = c; // save HTTP request character
req_index++;
}
// last line of client request is blank and ends with \n
// respond to client only after last line received
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
// remainder of header follows below, depending on if
// web page or XML page is requested
// Ajax request - send XML file
if (StrContains(HTTP_req, "ajax_inputs")) {
// send rest of HTTP header
client.println("Content-Type: text/xml");
client.println("Connection: keep-alive");
client.println();
SetLEDs();
// send XML file containing input states
XML_response(client);
}
// display received HTTP request on serial port
//Serial.print(HTTP_req);
// reset buffer index and all buffer elements to 0
req_index = 0;
StrClear(HTTP_req, REQ_BUF_SZ);
break;
}
// every line of text received from the client ends with \r\n
if (c == '\n') {
// last character on line of received text
// starting new line with next character read
currentLineIsBlank = true;
}
elseif (c != '\r') {
// a text character was received from client
currentLineIsBlank = false;
}
} // end if (client.available())
} // end while (client.connected())
delay(1); // give the web browser time to receive the data
client.stop(); // close the connection
} // end if (client)
}
// checks if received HTTP request is switching on/off LEDs
// also saves the state of the LEDs
void SetLEDs(void)
{
char str_on[12] = {0};
char str_off[12] = {0};
unsignedchar i;
unsignedint j;
int LED_num = 1;
for (i = 0; i < 3; i++) {
for (j = 1; j <= 0x08; j <<= 1) {
sprintf(str_on, "LED%d=%d", LED_num, 1);
sprintf(str_off, "LED%d=%d", LED_num, 0);
if (StrContains(HTTP_req, str_on)) {
LED_state[i] |= (unsignedchar)j; // save LED state
digitalWrite(LED_num + 25, HIGH);
Serial.println("ON");
}
elseif (StrContains(HTTP_req, str_off)) {
LED_state[i] &= (unsignedchar)(~j); // save LED state
digitalWrite(LED_num + 25, LOW);
}
LED_num++;
}
}
}
// send the XML file with analog values, switch status
// and LED status
void XML_response(Client cl)
{
unsignedchar i;
unsignedint j;
cl.print("<?xml version = \"1.0\" ?>");
cl.print("<inputs>");
for (i = 0; i < 3; i++) {
for (j = 1; j <= 0x08; j <<= 1) {
cl.print("<LED>");
if ((unsignedchar)LED_state[i] & j) {
cl.print("checked");
//Serial.println("ON");
}
else {
cl.print("unchecked");
}
cl.println("</LED>");
}
}
cl.print("</inputs>");
}
// sets every element of str to 0 (clears array)
void StrClear(char *str, char length)
{
for (int i = 0; i < length; i++) {
str[i] = 0;
}
}
// searches for the string sfind in the string str
// returns 1 if string found
// returns 0 if string not found
char StrContains(char *str, char *sfind)
{
char found = 0;
char index = 0;
char len;
len = strlen(str);
if (strlen(sfind) > len) {
return 0;
}
while (index < len) {
if (str[index] == sfind[found]) {
found++;
if (strlen(sfind) == found) {
return 1;
}
}
else {
found = 0;
}
index++;
}
return 0;
}
First: i kinda understand this "for (i = 26; i <= 49; i++)", but i'm not sure how to modify it for the output pins 1 - 8. should i write "for (i=1; i <= 9; i++)" ?
Yeah, It seems like he wants that outputs to be low at the beginning.
It is possible that your Leds turn on when setting the output to low though.
There are 2 ways to use a button or led: pull-up and pull-down
pull up means that a resistor is used to connect one side of the button/led with the supply voltage, pull down means a resistor is used to connect it to the ground.
Depending on what circuit a digital low as output can switch the led on or off.
And (unsigned char)~j ? what does that ~ do ?
the ~ inverts all bits for non-floating-point number types.
that means if your j looks like 1. then ~j looks like 2.
1 2
00101011
11010100
Third: i don't understand what does "char StrContains" .
It should tell you if a substring occures in str
for example:
Hallo has the substring all
And last : the "void XML_response(Client cl)" is made for and index.htm stored on an SD card. My controller does not have and SD slot, so i'll have to make the checkboxes or buttons in html.
Nah, not exactly. It just sends data to wherever cl has connected to, it only uses cl.print to send data so it is not specified foy anything.
You'll have to look at the header file of Client to find out more but I think the destination is decided in this line of code. Client client = server.available(); // try to get client
So, for it to make it work, what would you suggest me modify/discard/add ? Keeping in mind that i need to have at least 4 LEDs, on the 1 to 4 outputs and the fact that i need it to memorise the state of each LED. Because the problem i had with the last code, the one that was designed for only 1 LED, i made it work for 2 LEDs, but if i tried to make it work for a 3rd one, it would chaotically light them up.
and i will probably get rid of that XML response and just use html and css to make a little table with 4 checkboxes. i don't know how i'll do that yet, but i'll try.