Arduino, atoi, hex and decimal questions

Heya all, I have written a vbscript that spits out the cpu load in intervals:

strComputer = "."

Set objFSO=CreateObject("Scripting.FileSystemObject")

Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
set objRefresher = CreateObject("WbemScripting.Swbemrefresher")
Set objProcessor = objRefresher.AddEnum _
(objWMIService, "Win32_PerfFormattedData_PerfOS_Processor").objectSet
objRefresher.Refresh


Set fs=CreateObject("Scripting.FileSystemObject")
Set a = fs.CreateTextFile("COM7:9600,N,8,1",ForWriting)

Do
WScript.Sleep 1000
For Each intProcessorUse in objProcessor
If intProcessorUse.Name = "_Total" Then
a.write int(_
intProcessorUse.PercentProcessorTime)
End If
Next
objRefresher.Refresh
Loop
a.Close

It works and is sending the data to the Arduino. The problem is that my Arduino is receiving numbers such as “31 30” for say “10” and “33” for say “3”.

I opened up Serial Port Monitor and decided to manually send commands to the Arduino, using the String, Hex and Dec options. When I send numbers via a string, i.e. the number 30, it is actually sending it to the Arduino as “33 30”. When I select hex and send the same 30 (as 1E), it sends correctly. When I select dec and send the number 30, it its received by Arduino as 1E.

Is there a way to set the vbscript to send the numbers as a decimal? I tried sending the value as Hex

a.write Hex(_
intProcessorUse.PercentProcessorTime)

But what Arduino or my script does is it does the Hex of that value just as it did with the string.

I tried using atoi as well, but because the values being sent from my vbscript is a Hex of string, well, its not ascii so yeah…

Anyway, if only I could get the vbscript to send it in pure hex or as a decimal, it would work, but yeah. Anyone got any ideas? I need to be able to process values between 0-100. Thanks in advance!

The data being sent to the Arduino, when you send the number 30 as a string, 33 30, is the ascii representation of the number 3 in hex (33) and the ascii representation of the number 0 in hex (30).

When you send the number as a number, the 1E is the number 30 in hex.

In either case, the correct value is being sent. If you are having trouble on the Arduino end, it is a matter of misinterpreting the data received.

If we are to help you with that, we need to see the Arduino code.

/*
This script will allow the Arduino board to receive input values from
the PC via the serial port and output them to the RGB LEDs, fading them up/down.
*/

// Pins
int redPin = 3;
int greenPin = 5;
int bluePin = 6;

// Colors
int cRed[100];
int cGreen[100];
int cBlue[100];

// Counters
int nRed = 0; // Dimmest of all
int nGreen = 255; // Very bright
int nBlue = 155; // Moderately bright
int nConnect = 0;

// Timers
int tStep = 40; // Sets fader step duration, (tStep*100)/1000 < tRefresh
int tBlink = 50; // Sets blink rate
int tRefresh = 5000; // Sets the time between input refresh

// Load
int cLoad = 0; // Current Load
int pLoad = 0; // Previous Load

// Initialize Setup
void setup()
{
  Serial.begin(9600); // Open serial communication
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  
  // Map Red and Blue Colors
  for (int i = 0; i <=100; i++) {
    cRed[i] = nRed;
    nRed = nRed + 1;
    cBlue[i] = nBlue;
    nBlue = nBlue + 1;
  }
  
  // Map Green Colors (First Half)
  for (int i = 0; i <= 50; i++) {
    cGreen[i] = nGreen;
    nGreen = nGreen - 1; 
  }
   
  // Map Green Colors (Second Half)
  for (int i = 51; i <= 100; i++) {
    cGreen[i] = nGreen;
    nGreen = nGreen + 1; 
  }  
  
  // Initialize starting state
  analogWrite(redPin,255);
  analogWrite(greenPin,255);
  analogWrite(bluePin,255);
  delay(tStep);
  
  // Cycle through colors on initial bootup starting from 100-0%
  for(int i = 100; i >= 0; i--) {
    analogWrite(redPin,cRed[i]);
    analogWrite(greenPin,cGreen[i]);
    analogWrite(bluePin,cBlue[i]);
    delay(tStep);
    if (i == 0) {
      for(nConnect = 0; nConnect == 1;) {
        analogWrite(bluePin,255);
        delay(tBlink);
        analogWrite(bluePin,cBlue[i]);
        delay(tBlink);
        if(Serial.available() > 0) {
          nConnect = nConnect + 1;
        }
      } 
      nConnect = 0; // Reset
    }
  }
}

// Fader based on serial input (0-100% CPU Load)
void loop(){
  
  // If serial communication established and receiving 
  if (Serial.available() >0) {
    delay(tRefresh);
    pLoad = cLoad; // Grab previous value
    cLoad = Serial.read();
    // Check to make sure serial input is between 0-100%
    if(cLoad >= 0 && cLoad <= 100){
      // If current value is greater then previous value - Initiate Fade Up
      if (cLoad > pLoad) {
        for(int i = pLoad; i >= cLoad;i++) {
          analogWrite(redPin,cRed[i]);
          analogWrite(greenPin,cGreen[i]);
          analogWrite(bluePin,cBlue[i]);
          delay(tStep);
        }
      }
      // If current value is less then previous value - Initiate Fade Down
      if (cLoad < pLoad) {
        for(int i = pLoad; i <= cLoad; i--) {
          analogWrite(redPin,cRed[i]);
          analogWrite(greenPin,cGreen[i]);
          analogWrite(bluePin,cBlue[i]);
          delay(tStep);
        }
      }
      // If current value is equal to the previous value - Do Nothing
    }
    Serial.flush(); // Clear out serial value
  }
}

Its a bit messy atm as I typed it out at work. I had tried using ATOI when receiving the value from my PC using the vbscript above. Thanks!

P.S. The RGB LED colors are different because I found that the ones I purchased, the red ones were not as luminant as the green, so thats why the values are a bit different.

Perhaps I misunderstood the initial question. I re-read the first post, and I see that you are opening the com port as a text file. So, the data being written to that file will be text. So, the int conversion is unnecessary.

Instead, you will need to make the Arduino read the string that is sent. Fortunately, that is easy.

First, you need to add start and end data markers in the VB application. This is necessary because the VB app is currently sending data like this:

‘3’, ‘0’, ‘4’, ‘1’, ‘7’, ‘6’,…

Hard to tell where the data for one value starts and ends. This is much clearer:

‘<’, ‘3’, ‘0’, ‘>’, ‘<’, ‘4’, ‘1’, ‘>’, ‘<’, ‘7’, ‘6’, ‘>’, ‘<’,…

I presume you can make the VB application output the start and end markers.

On the Arduino side, then, you need to create a character array, and store the data in that array.

char cpuLoadStg[4]; // Large enough for '1', '0', '0', & NULL
int cpuIndex;
boolean started = false;
boolean ended = false;

void loop()
{
   if(Serial.available() > 0)
   {
      while(Serial.available() > 0)
      {
         char aChar = Serial.read();
         if(aChar == '<')
         {
            cpuIndex = 0;
            started = true;
         }
         else if(aChar == '>')
            ended = true;
         else
         {
            cpuLoadStg[cpuIndex] = aChar;
            cpuIndex++;
            cpuLoadStg[cpuIndex] = '\0';
         }
      }
   }

   if(started && ended)
   {
      // Convert cpuLoadStg to integer, using atoi
      // Do whatever needs to be done with integer value
      started = false;
      ended = false;
   }
}

Thanks PaulS, I am going to give that a try when I go home. Cheers.

    // Parse incoming data
    char inputValue[4]; // Large enough for '1', '0', '0', & NULL
    int cpuIndex;
    boolean rStart = false;
    boolean rEnd = false;
    
    // While serial is available
    while(Serial.available() > 0)
    {
      char aChar = Serial.read(); // Capture each character from serial
      if(aChar == '<')
        {
          cpuIndex = 0;
          rStart = true;
            } else if(aChar == '>') {
          rEnd = true;
            } else if (rStart == true && rEnd == false) {
          inputValue[cpuIndex] = aChar;
          cpuIndex++;
          inputValue[cpuIndex] = '\0';
            }
    }
  
     if(rStart && rEnd)
     {
        // Convert cpuLoadStg to integer, using atoi
        cLoad = atoi(inputValue);
    
        // Do whatever needs to be done with integer value
        rStart = false;
        rEnd = false;
     }

Hi Paul, I tried using that code, but to no avail. I have my vbscript sending the start and end markers ‘<’ and ‘>’ and I do see it coming through as ascii hex values 3c and 3e in the serial port sniffer. I fear that I may not have used atoi properly. Thanks in advance!

Two thoughts. One is that serial communication can be two-way. Have the Arduino send messages back to the VB application to read and display.

Second is that I don't see anything wrong with the code you posted, and you didn't explain what didn't work, and you didn't post all of your code, so I can't see where cLoad is being used after it is set.