Char Array Question

Hi Forum, I have connected a 74hc595 shift register to an Arduino UNO and want to make some simple functions in order to control it. I have however a strange problem when assigning the last bit in the array. As far as I know the last bit should be ‘\0’ for a char array. I have therefore created char array of length 9 (Valves). When I loop from 0 to 6 i updateAllValve(), these valves is updated correctly, however when i loop from 0 to 7 (which I want), nothing happens. The setValves() function is run but when I look at the physical output (the valve actuation) nothing happens?

#define number_of_74hc595s 1
#define numOfRegisterPins number_of_74hc595s * 8
#define closed ‘0’
#define opened ‘1’

char Valves[numOfRegisterPins+1];

void setValves(){
Serial.print(Valves);
int val;
for(int i = numOfRegisterPins - 1; i >= 0; i–){
digitalWrite(SRCLK_Pin, LOW);
if(Valves == ‘1’){

  • digitalWrite(SER_Pin, HIGH);*

  • } else {*

  • digitalWrite(SER_Pin, LOW);*

  • }*

  • digitalWrite(SRCLK_Pin, HIGH);*

  • }*

  • Serial.println();*

  • digitalWrite(RCLK_Pin, HIGH);*

  • digitalWrite(RCLK_Pin, LOW);*
    }
    void updateAllValve(String openClose){

  • for (int i=0; i<numOfRegisterPins-1; i++){*

  • if(openClose==“closeAll” or openClose==“close”){*
    _ Valves = closed;_
    * }else{*
    _ Valves = opened;
    * }
    }
    Valves[numOfRegisterPins] = ‘\0’;
    setValves();
    }*
    Thanks!_

Please put code in CODE tags. And post the entire program if possible.

last bit should be '\0' for a char array.

It's the last byte, not bit.

if(Valves == '1'){

Valves can never == '1', it's an array of characters. I don't know how it worked with a loop of 6 and not 7. Try

if(Valves[i] == '1'){

nothing happens

What is the result of the Serial.print(Valves);, is the array correct?


Rob

Valves can never == '1', it's an array of characters.

That is a direct result of improperly posting code. The original code had [ i ], but since that is the italic flag, the rest of the line (and subsequent lines) are in italics.

Until the code is posted correctly, I won't even bother reading it anymore, just because of issues like this. And, of course, the lack of manners of the OP, who clearly didn't read the "How to post in this forum" post before posting.

That is a direct result of improperly posting code.

Dang, I should be a wake up to that by now :)

In my defence it was at about 5:30AM and I went to bed at 1:30.


Rob

You only need a ‘\0’ at the end of an array of characters if you are using it as a string. If you are just using it as an array of characters, i.e., referencing individual array elements, then you don’t need the ‘\0’. The ‘\0’ is only used by internal functions that manipulate the array as a whole, such as strlen(), strcpy(), printf(), etc.

Hi, thanks for the feedback, really appreciate it. It is true that this is the result to the error: (Valves == ‘1’){
I changed this, but still have the error. (I think I forgot to change it back properly after trying something else).
This is the complete code. I tried to only show the part that was interesting for the problem, but here is the complete code:
```
*#include <ctype.h>

#define number_of_74hc595s 1
#define numOfRegisterPins number_of_74hc595s * 8
#define closed ‘0’
#define opened ‘1’

int SER_Pin = 8;    //pin 14 on the 75HC595 Grøn
int RCLK_Pin = 9;  //pin 12 on the 75HC595 Blå
int SRCLK_Pin = 10; //pin 11 on the 75HC595 Gul

byte rx = 3; //sort
byte tx = 4; //gul
byte SWval;

char Valves[numOfRegisterPins+1];

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(SER_Pin, OUTPUT);
  pinMode(RCLK_Pin, OUTPUT);
  pinMode(SRCLK_Pin, OUTPUT);
  pinMode(rx,INPUT);
  pinMode(tx,OUTPUT);
  digitalWrite(tx,HIGH);
  Serial.begin(9600);
  initPump();
  updateAllValve(“closeAll”);
}

void sentChar(int data)
{
  byte mask;
  //startbit
  digitalWrite(tx,LOW);
  delayMicroseconds(104);
  for (mask = 0x01; mask>0; mask <<= 1) {
    if (data & mask){ // choose bit
    digitalWrite(tx,HIGH); // send 1
    }
    else{
    digitalWrite(tx,LOW); // send 0
    }
    delayMicroseconds(104);
  }
  //stop bit
  digitalWrite(tx, HIGH);
  delayMicroseconds(5);
}

int readChar()
{
  byte val = 0;
  while (digitalRead(rx));
  //wait for start bit
  if (digitalRead(rx) == LOW) {
    delayMicroseconds(46);
    for (int offset = 0; offset < 8; offset++) {
    delayMicroseconds(92);
    val |= digitalRead(rx) << offset;
    }
    return val;
  }
}

//Set and display registers
//Only call AFTER all values are set how you would like (slow otherwise)

void setValves(char inp){
  int val;
  for(int i = numOfRegisterPins - 1; i >=  0; i–){
    digitalWrite(SRCLK_Pin, LOW);
    if(inp[i] == ‘1’){
      digitalWrite(SER_Pin, HIGH);
    } else {
      digitalWrite(SER_Pin, LOW);
    }
    digitalWrite(SRCLK_Pin, HIGH);
  }
  Serial.println();
  digitalWrite(RCLK_Pin, HIGH);
  digitalWrite(RCLK_Pin, LOW);
}

void setValves(){
  Serial.print(Valves);
  int val;
  for(int i = numOfRegisterPins - 1; i >=  0; i–){
    digitalWrite(SRCLK_Pin, LOW);
    if(Valves[i] == ‘1’){
      digitalWrite(SER_Pin, HIGH);
    } else {
      digitalWrite(SER_Pin, LOW);
    }
    digitalWrite(SRCLK_Pin, HIGH);
  }
  Serial.println();
  digitalWrite(RCLK_Pin, HIGH);
  digitalWrite(RCLK_Pin, LOW);
}

void updateValve(int number, String openClose){
  if((openClose==“closeAll” or openClose==“close”) and number < numOfRegisterPins){
    Valves[number] = closed;
    Serial.print(“close”);}
  else
    Valves[number] = opened;
  setValves();
}

void updateAllValve(String openClose){
 
  for (int i=0; i<numOfRegisterPins; i++){
    if(openClose==“closeAll” or openClose==“close”){
      Valves[i] = closed;
    }else{
    Valves[i] = opened;
    }
  }
  Valves[numOfRegisterPins] = ‘\0’;
  setValves();
}

void dispense(String pump, String amount){
  char msg[8];
  int a =  pump.substring(4).toInt();
  char XOR = 2^48+a^‘1’^‘D’;
 
  sentChar(2);
  sentChar(48+a);
  sentChar(‘1’);
  sentChar(‘D’);
  for (int i=0; i<amount.length();i++){
    sentChar(amount[i]);   
    XOR = XOR^amount[i];
  }
  sentChar(‘R’);
  sentChar(3);
  sentChar(XOR);
}

void setRate(String pump, int rate){

}

void reload(String pump){

}

void initPump(){
 
}

// the loop routine runs over and over again forever:
void loop() {

char a = readChar();
 
  updateAllValve(“openAll”);
  delay(500);
  updateAllValve(“closeAll”);
  delay(500);

sentChar(‘h’);
  sentChar(‘e’);
  sentChar(‘l’);
  sentChar(‘l’);
  sentChar(‘o’);
  sentChar(’ ‘);
  sentChar(‘w’);
  sentChar(‘o’);
  sentChar(‘r’);
  sentChar(‘l’);
  sentChar(‘d’);
  sentChar(’!’);
}*
```
In the serial output I get this when looping from 0 to 6:
0000000
1111111
0000000
The sound from the valves is also there
however when I loop to 7, the serial output is there, but the sound is not.
00000000
11111111
00000000
Thanks again!

Why not eliminate possible problems with your shifting code and build up your valve on/off statuses into bytes with bitwise operators and bitshifting, then use the normal shiftOut() function to shift the byte out to the shift register?

void setValves(char inp[]){
  byte oval = 0;
  byte bits = 0;

  for (byte i = 0; i  < numOfRegisterPins; i++) {
    oval <<= 1;
    oval |= inp[i] == '1' ? 1 : 0;
    bits++;
    if (bits == 8) {
      shiftOut(SER_Pin, SRCLK_Pin, MSBFIRST, oval);
      oval = 0;
      bits = 0;
    }
  }
  if (bits != 0) {
    shiftOut(SER_Pin, SRCLK_Pin, MSBFIRST, oval);
  }
  Serial.println();
  digitalWrite(RCLK_Pin, HIGH);
  digitalWrite(RCLK_Pin, LOW);
}

Or words to that effect.

Or better still, why not scrap the whole array and just use a single variable with enough space for all your valves? They are either on or off, that’s 1 or 0 - that’s binary that is. A byte could store 8 valves. An int could store 16. A long could store 32 valves - that’s just 4 bytes for a whole 32-valve set - and they could be shifted out with shiftOut() very very simply.

Thanks for this input, I will have to look into this way of doing it. However this is not the function that causes the problem. There are two functions with the same name but different input parameters. One uses the Global char array Valves, and the other uses and input char array like this setValves("10101010"). It is the function bellow that has the problem.

void setValves(){
  Serial.print(Valves);
  int val;
  for(int i = numOfRegisterPins - 1; i >=  0; i--){
    digitalWrite(SRCLK_Pin, LOW);
    if(Valves[i] == '1'){
      digitalWrite(SER_Pin, HIGH);
    } else {
      digitalWrite(SER_Pin, LOW);
    }
    digitalWrite(SRCLK_Pin, HIGH);
  }
  Serial.println();
  digitalWrite(RCLK_Pin, HIGH);
  digitalWrite(RCLK_Pin, LOW);
}

That's a bit silly, when they both do the same thing.

Why not:

void setValves() {
  setValves(Valves);
}

Thanks alot guys!

Another thing you could do is combine the two functions into one by providing a default value:

char Valves[8] = { '1', '0', '1', '0', '1', '0', '1', '0' };;

// Note: the preprocessor code doesn't identify this format 
// of function so doesn't create a prototype for it - make sure
// it's defined before you use it, or make your own prototype.

// If you don't provide a parameter then "v" will equal NULL.
void setValves(char *v = NULL) {
	// If "v" is null then assign "Valves" to "arr", otherwise assign "v" to "arr".
	char *arr = v == NULL ? Valves : v;
	// Do things with "arr".
	for (int i = 0; i < 8; i++) {
		Serial.print(arr[i]);
	}
	Serial.println();
}

void setup() {
	Serial.begin(9600);
}

void loop() {
	// Send the "Valves" settings
	setValves();
	delay(100);

	// Send specific settings
	setValves("00001111");
	delay(100);
}