Go Down

Topic: Sorting by light (Read 2257 times) previous topic - next topic

Nagaro

You're right, actually i'm only reading 1 byte with this code, when i should check 2 or more. I'm checking at the moment on the forum how to do so.
Thank you for pointing it out, i didn't know about it.
Everyday is a learning day :-)

Otherwise, i've tested my macro with the arduino again this morning, and it actually works as it should. The problem is that i have the feeling that the macro is running too fast, and the arduino doesn't have the time to react and get the data correctly. And therefore fails and doesn't switch on any light or switches on the wrong one.
So i need to find a way to slow down my macro, that the arduino can react.

Is this analysis possible ? Or can there be another reason, or something i should actually add in the arduino code rather than the vba code ?

Grumpy_Mike

Quote
Is this analysis possible
No.
The speed is restricted by the serial baud rate at both ends. Also both ends have buffers so unless you over run them you will not loose any data.

If you want to make double sure have the Arduino send an acknowledgment byte and don't send any more data from the PC until it gets the acknowledgment of the previous one. But I doubt it is your problem.

Nagaro

I was checking again, and i've figured out that the macro is opening the port, send the information and closes it again.
But it is so fast that the port doesn't have the time to open that the information have been already sent. So it never arrived to the arduino. Adding a line like « sleep 1500 ms » after opening the port gives the possibility to the data to reach the arduino. But obviously i'm loosing time, as i need to wait 1,5 seconds every time.

Do you know if i can leave the port open all the time, without havkng to close it and open it again everytime i want to send a data to the arduino ?

Grumpy_Mike

Every time the port is opened then the Arduino is reset.

Quote
Do you know if i can leave the port open all the time, without havkng to close it and open it again everytime i want to send a data to the arduino ?
You should be able to do that but it is a PC problem rather than an Arduino one, unless you want to disable the auto reset on the Arduino.

Nagaro

#34
May 07, 2018, 10:46 pm Last Edit: May 07, 2018, 10:53 pm by Nagaro
OK, i'll investigate on this direction.

I updated my Arduino code, to be able to read more than 1 byte (in this example 2).
But anyhow nothig happens on the leds. I believe there is a mistake in the code, but i don't find it.
I've realized that the previous code contained Serial.readString; when this one uses Serial.read.  ut when i replace it to readString, it doesn't work as it uses a char and not a string.
The issue might also code from the fact that i convert a char into a int with the atoi function.

Can somebody have a look ? Grumpy_Mike maybe, who is a really good helper on this forum ?

Code: [Select]

#include <FastLED.h>
#define LED_PIN     7 // input in arduino nano (here A7)
#define NUM_LEDS    60 // number of leds
CRGB leds[NUM_LEDS];

const byte numChars = 2;
char receivedChars[numChars]; // an array to store the received data

boolean newData = false;

void setup() {
 Serial.begin(9600);
 // Serial.println("<Arduino is ready>");
 FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
}

void loop() {
 recvWithEndMarker();
 updateLEDnumber();
}

void recvWithEndMarker() {
 static byte ndx = 0;
 char endMarker = '\n';
 char rc;
 
 if(Serial.available())
{
while (Serial.available() > 0 && newData == false)
{
rc = Serial.read();

if (rc != endMarker)
{
receivedChars[ndx] = rc;
ndx++; // continue the string
if (ndx >= numChars)
{
ndx = numChars - 1;
}
}
else
{
receivedChars[ndx] = '\0'; // terminate the string
ndx = 0;
newData = true;
}
}
}

}



void updateLEDnumber() {
 if (newData == true) {

int value = atoi(receivedChars); // convert char in integer
leds[value & 0xF] = CRGB(255, 0, 0);
FastLED.show();
// delay(100);
// Serial.print("This just in ... ");
// Serial.println(receivedChars);
newData = false;
 }
}





Thank you,

Grumpy_Mike

If you are using atoi to do the conversion then the receivedChars array must be a null terminated string. As you only have two bytes in that array you can only put a one digit number in it.
In the function where you read the serial input
Code: [Select]
receivedChars[ndx] = '\0'; // terminate the string
you make no check that ndx is within the array size, so you are stamping on some other memory location. This can cause strange errors as it can change another variable without you realising it.
So give the receivedChars array at least one more byte than you are expecting.

Nagaro

#36
May 08, 2018, 10:28 pm Last Edit: May 08, 2018, 10:29 pm by Nagaro
Hi Grumpy_Mike and all others,

I reviewed completely my codes, and now i have something working really good.
The excel sheet is sending the info to the Arduino on which led to switch on, and with which color.

I attach my excel file, and post below the arduino code.
I believe it can be improved (still this time i need to wait after the port is open that the info is sent to the arduino; which is at the moment 1,5 seconds waste), maybe you'll find some ideas.

Thank you all again for wour support, i might post new questions if i have some.

Code: [Select]

#include <FastLED.h>
#define LED_PIN     7
#define NUM_LEDS    60
CRGB leds[NUM_LEDS];

const byte numChars = 32;
char receivedChars[numChars];

boolean newData = false;

void setup() {
  FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
    Serial.begin(9600);
    Serial.println("<Arduino is ready>");
}

void loop() {
    recvWithStartEndMarkers();
    showNewData();
}

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;
 
 // if (Serial.available() > 0) {
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read(); //Format of info to send : <00.000.000.000>

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

void showNewData() {
    if (newData == true) {

      //declare LED number to switch on

      String RCstr(receivedChars);
      String RCmid;
      RCmid = RCstr.substring(0, 2);
      int RCnum = RCmid.toInt();

      //declare RED color

      String REDstr;
      REDstr = RCstr.substring(3, 6);
      int REDnum = REDstr.toInt();

      //declare GREEN color

      String GRstr;
      GRstr = RCstr.substring(7, 10);
      int GRnum = GRstr.toInt();

      //declare BLUE color

      String BLstr;
      BLstr = RCstr.substring(11, 14);
      int BLnum = BLstr.toInt();

      //switch on LED
      leds[RCnum] = CRGB(REDnum, GRnum, BLnum);
      FastLED.show();
      delay(100);
        Serial.print("This just in ... ");
        Serial.println(receivedChars);
        Serial.println(RCnum);
        Serial.println(REDnum);
        Serial.println(GRnum);
        Serial.println(BLnum);
        newData = false;
    }
}


Grumpy_Mike


Nagaro

#38
Apr 12, 2019, 05:58 pm Last Edit: Apr 12, 2019, 05:59 pm by Nagaro
Hi,

I'm back with this « Sorting by light ».
I've been using it for a while now, nevertheless the 1.5 seconds to wait between the transfer of data from excel and the light switching on on the Arduino is a real bottleneck.

Would anybody have any idea on how to solve this ?
I'm so close to the conclusion that i don't want to give up :-)

Thank you,

Grumpy_Mike

 Think most of the delay is outside the Arduino. However, to speed up that Arduino code:-

Remove all delay calls.
Increase the baud rate and / or remove the serial prints outside the start up function.
Do not use Strings variables, use string variables the capital S makes a big difference.
Do not keep defining variables in the display function. Have the defined either globally or define them as static.

Nagaro

#40
Apr 17, 2019, 07:00 pm Last Edit: Apr 17, 2019, 07:03 pm by Nagaro
Hi Grumpy_Mike,

Nice to read you again :-)

Thank you for these advices.
I've read somewhere that an arduino needs about 2 seconds to « switch on », probably to initialize its internal program.
Somehow i have the feeling that everytime i inject the variable from pc to arduino, it restarts it. Therefore this delay of 1.5 sec.

Do you think there would be a way that i don't need to reinitialize always the arduino, that the variables are updated directly ? Is this what you mean with moving the variables in the display function (is it actually the line char receivedChars[numChars]; that you refer to) ?

Grumpy_Mike

Quote
I've read somewhere that an arduino needs about 2 seconds to « switch on », probably to initialize its internal program.
That is true but it is not to initialise internal variables it is the boot loader sending a message through the serial port asking if there is a program to upload and waiting for any reply. If no reply than it runs the code it already has.

Each time the PC sends any serial data it opens the serial port which resets the Arduino.

There are several ways round this. One it to disable the auto interrupt circuit by either cutting a track or putting a large capacitor between the reset pin and ground. 10uF should do. I have one Arduino with a cut track and a slide switch across it so I can simply enable / disable the interrupt.

Another option is to remove the boot loader altogether and program the Arduino direct with a programmer or another Arduino programmed to look like a programmer.

Go Up