Go Down

Topic: Help understanding (char *). (Read 686 times) previous topic - next topic

Pavilion1984

May 11, 2012, 01:43 pm Last Edit: May 11, 2012, 01:54 pm by Pavilion1984 Reason: 1
Hi all.

Can anyone explain to me why the (char *) has to be in brackets in this line of code.

Code: [Select]
ELM_Transmit((char *)ECT);

(ECT is #define ECT "0105"

Many thanks.

pYro_65

#1
May 11, 2012, 01:46 pm Last Edit: May 11, 2012, 01:47 pm by pYro_65 Reason: 1
it is being converted to a char pointer ( also can be viewed as an array of char )
This makes it easy to send large data structures 1 byte at a time.

The #define 0105 must be a particular known memory location.

SurferTim

That is a type cast. The function ELM_transmit() is apparently expecting a character pointer. If the variable type of ECT is not a character pointer (a byte pointer for example), you would need to tell the function that the data type is correct, despite what it thinks.

Pavilion1984

#3
May 11, 2012, 01:49 pm Last Edit: May 11, 2012, 01:53 pm by Pavilion1984 Reason: 1
Ok thanks. Can you tell me why it needs the brackets?

Many thanks.

Sorry just noticed its #define ECT "0105".

SurferTim

#4
May 11, 2012, 01:53 pm Last Edit: May 11, 2012, 01:58 pm by SurferTim Reason: 1
That is the format for a type cast. The function has been declared something like this
void ELM_transmit(char* myChar);
and the variable like this
byte ECT[12];
then calling the function with ECT as a parameter would cause a type error. The (char*) tells the compiler treat this variable as a character pointer, not a byte pointer as declared.

edit: I see your edit. The define probably assigns the data type on that as a String variable. Then you need to tell the compiler it is not really a string, but an array of characters.





wildbill

Looks like an unnecessary cast to me - passing a string (not String) literal to a function expecting a char * is quite acceptable - what does the compiler say if you omit it?

Pavilion1984

Many thanks all and the compiler likes it wildbill.

Am new at this and writen some code that works (below) but just can't help thinking it's the long way round and it could be more flexible. Tacke a look and tell me what you think but this is all new to me so learning all the way lol.

Code: [Select]
//LCD setup.
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
#define Rows 2
#define Columns 16

#define Shift_LED 13

//ELMxxx AT commands.
#define ELM_RESET                    "ATZ\r"
#define ELM_DEFAULTS                 "ATD\r"
#define ELM_ECHO_OFF                 "ATE0\r"
#define ELM_LINEFEEDS_OFF            "ATL0\r"

//Vehicle PIDs.
#define ECT                          "0105"
#define ERPM                         "010C"
#define VS                           "010D"
#define EOT                          "015C"

#define NULL '\0'                                //ASCII null char.
#define PROMPT '>'                               //ASCII prompt char.

char ELM_Rx[16];                                 //ELM receive buffer.

char Byte_A[3];                                  //Byte A of PID response.
char Byte_B[3];                                  //Byte B of PID response.
byte Byte_AH;                                    //Byte A, HEX converted ASCII.
byte Byte_BH;                                    //Byte B, HEX converted ASCII.

void setup()
{
  Serial.begin(9600);                            //Initialize the serial communication.
  lcd.begin(Rows, Columns);                      //Initialize the LCD.
 
  pinMode(Shift_LED, OUTPUT);

  lcd.setCursor(3,0);
  lcd.print("OBDuno323.");
  lcd.setCursor(6,1);
  lcd.print("v0.b");
  delay(2000);
  ELM_Init();
  lcd.clear();
}

void ELM_Init()
{
  lcd.clear();
  lcd.setCursor(2, 0);
  lcd.print("Initialising");
  Serial.print(ELM_RESET);
  delay(1000);
  Serial.print(ELM_ECHO_OFF);                    //Turns the echoing of sent commands off.
  delay(500);
  lcd.clear();
  lcd.setCursor(2, 0);
  lcd.print("Initialising");
  lcd.setCursor(6, 1);
  lcd.print("Done");
  delay(1500);
}

void loop()
{
  Serial.print(getERPM());
  /*
  lcd.setCursor(0, 0);
  lcd.print(getERPM());
  if(getERPM() >= 3000)
  {
    digitalWrite(Shift_LED, HIGH);
    delay(50);
    digitalWrite(Shift_LED, LOW);
    delay(50);
  }
  */
}

byte ELM_Transmit(char* PID)
{
  Serial.println(PID);
}

int ELM_Read()
{
  char temp;
  byte i = 0;
  do
  {
    temp = Serial.read();
    if (temp >= ' ')
    {
      ELM_Rx[i++] = temp;
    }
  }
  while (temp != PROMPT);
 
  ELM_Rx[i -1] = NULL;
 
  if (i == 9)
  {
    Byte_A[0] = ELM_Rx[6];
    Byte_A[1] = ELM_Rx[7];
    Byte_A[2] = NULL;
   
    Byte_AH = strtoul(Byte_A, NULL, 16);
   
    return 1;                                    //No error in response lengh.
  }
  else if (i == 13)
  {
    Byte_A[0] = ELM_Rx[6];
    Byte_A[1] = ELM_Rx[7];
    Byte_A[2] = NULL;
   
    Byte_B[0] = ELM_Rx[9];
    Byte_B[1] = ELM_Rx[10];
    Byte_B[2] = NULL;
   
    Byte_AH = strtoul(Byte_A, NULL, 16);
    Byte_BH = strtoul(Byte_B, NULL, 16);
   
    return 1;                                    //No error in response lengh.
  }
  else
  {
    return 0;                                    //Error in response lengh.
  }
}

//Engine coolant temperature block.
int getECT()                                     //Engine Coolant Temperature.
{
  int result;                                    //Variable to store calculation result.
  ELM_Transmit((char*) ECT);
  if (ELM_Read() == 1)                           //Calls the ELM_Read block.
  {
    result = Byte_AH - 40;                       //Function calculation.
    return result;
  }
  else
  return 0;
}

//Engine RPM block.
int getERPM()                                    //Engine RPM.
{
  int result;                                    //Variable to store calculation result.
  ELM_Transmit((char*) ERPM);
  if (ELM_Read() == 1)                           //Calls the ELM_Read block.
  {
    result = ((Byte_AH * 256) + Byte_BH) / 4;    //Function calculation.
    return result;
  }
  else
  return 0;
}

//Vehicle speed block.
int getVSPD()                                    //Vehicle Speed.
{
  int result;                                    //Variable to store calculation result.
  ELM_Transmit((char*) VS);
  if (ELM_Read() == 1)                           //Calls the ELM_Read block.
  {
    result = Byte_AH;
    return result;
  }
  else
  return 0;
}

//Engine oil temperature block.
int getEOT()                                     //Engine Oil Temperature.
{
  int result;                                    //Variable to store calculation result.
  ELM_Transmit((char*) EOT);
  if (ELM_Read() == 1)                           //Calls the ELM_Read block.
  {
    result = Byte_AH - 40;                       //Function calculation.
    return result;
  }
  else
  return 0;
}

pYro_65

#7
May 11, 2012, 02:21 pm Last Edit: May 11, 2012, 02:28 pm by pYro_65 Reason: 1
Regarding omitting the type cast

If the transmit function parameter type is 'const char*' everything is fine.

If the type is just 'char*' it works for now, but is a feature marked as deprecated, which may not exist in the newer or future versions of GCC

Pavilion1984

Ok thanks, so it may not be good to use it then.

One more thing with this code is when i print getERPM(); to the LCD and the value is 3200 lets say and when the value gets down to 892 the 3 still remains on the lcd like 3892? Also i want my LCD to say RPM 3200 but i get errors when i try and do lcd.print("RPM ", getERPM());?

Thanks again.

pYro_65

There is a number of ways to do this.

Use an array of spaces long enough for the number, copy your value in from the end.
Then display that array, unused columns at the start are already filled with spaces.

Or count the string, if less than max print ( max - length ) spaces before printing the number.

Also depends on how the LCD handles text.

Pavilion1984

It's just a standard 16x2 LCD an thanks, any examples of what you said with an array?

Thanks.

pYro_65

This is not tested but shows my intention.

Code: [Select]

void PadText4( char *c_Text )
 {
   byte b_Cursor   = strlen( c_Text );

   if( b_Cursor < 4 ){

     char c_Buffer[] = "    ";
     byte b_Index   = 4;

     while( b_Cursor )
        c_Buffer[ --b_Index ] = c_Text[ --b_Cursor ];
     lcd.print( c_Buffer );

   }else{

     lcd.print( c_Text );
   }
   return;
 }


Can easily change to handle padding of variable length.

Go Up