c++ related project

Hello !

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
Hey, first of all welcome here.

The question you ask for is more or less microcontroller related but I try to answer whatever I can ^^

To be easier to read: here is the code with the code tag:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
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;
}


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
Hi and thank you for taking the time to answer.

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.
4 LEDs, on the 1 to 4 outputs

set those pins as outputs and then try to find out if the leds shine if the output is high or low (or you can use your brain for that ;) )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// in global scope
unsigned char led_states = 0;

enum { Led1 = 0x01, Led2 = 0x02, Led3 = 0x04, Led4 = 0x08 };
const unsigned char led_count = 4;

// to switch leds on
void led_on(unsigned char led_mask) {
    led_states |= led_mask; // binary or-equals: 10 |= 01 => 11
    for(int i = 1; i <= led_count; ++i) {    
        digitalWrite(i, bool(led_states & (1 << (i-1))) == HIGH); // you might need to change HIGH to LOW
    }
}
// to switch leds off
void led_off(unsigned char led_mask) {
    led_states &= ~led_mask; // binary and-equals-inversion: 11 &= ~01 => 10
    for(int i = 1; i <= led_count; ++i) { 
        digitalWrite(i, bool(led_states & (1 << (i-1))) == HIGH); // you might need to change HIGH to LOW
    }
}

// to use this:
{
    led_on(Led1|Led2|Led3); // use binary or-operator
                                          // switches on Led 1-3
    led_off(Led1|Led3) // switches off Led 1 and Led 3
}

// in setup
for(int i = 1; i <= 4; ++i) {
    pinmode(i, OUTPUT);
    digitalWrite(i, LOW); // switch the output pins off
}


I hope I didn't make any mistakes
Last edited on
Thank you! i will give it a try as soon as i get home and i'll come with un update
Topic archived. No new replies allowed.