Author Topic: Program stuck with simple math operations.  (Read 5231 times)

0 Members and 1 Guest are viewing this topic.

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3146
  • Country: ca
Re: Program stuck with simple math operations.
« Reply #25 on: October 10, 2017, 02:02:59 am »
The debugger doesn't halt here, I'm not sure if I'm being explicit enough but the uC is the one who just stops responding in the UART comm, the debuger helps not much here since when it goes to that line it enters an assembler routine and just loops the crap out of it for who knows how long..

What values are you feeding to this routine?
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: Program stuck with simple math operations.
« Reply #26 on: October 10, 2017, 02:03:15 am »
The debugger doesn't halt here, I'm not sure if I'm being explicit enough but the uC is the one who just stops responding in the UART comm, the debuger helps not much here since when it goes to that line it enters an assembler routine and just loops the crap out of it for who knows how long..

What is the code address of the loop?  What did the linker put there?  You need the linker produced map and, if possible, a complete assembly code listing.

If you wipe out the stack by bumping into something, some return address is likely to get hosed.  The uC will then return to some arbitrary place that may not even exist.

Speed of execution doesn't favor floating point by at least an order of magnitude in execution time.  Maybe you app won't be impacted.

I almost never use floats and I try to avoid GCCs printf() because it brings along a requirement for a heap and I want to avoid malloc() at all possible costs.  I copy my conversion routines from Kernighan & Ritchie "The C Programming Language" and avoid using library functions.

The memory is usually laid out from low to higher addresses as initialized variables, followed by allocated non-initialized variables, followed by the heap (grows toward high memory) and finally, the stack (grows from high memory toward low memory.  You don't use the heap directly but there is a bunch of library code that does.  Function arguments, function return values, function local variables and return addresses are kept on the stack.  You don't have much to do with stack growth.

I would take every opportunity to get rid of the floating point.  It will reduce your code size substantially and probably help with stack and heap usage.  Besides, integer arithmetic is faster by an order of magnitude (just guessing). 

If x is a float, you can't get an exact comparison as in 'if (x == 3.0) { }' because the computer can't represent 3.0 perfectly.  Sometimes you have to do something like 'if (abs(x - 3.0) < epsilon) {}' where epsilon is some small value like 1.0e-6 (varies depending on how many significant digits your floating point library carries).  It's a 'close enough' approximation that x is equal to 3.0.

 

Offline zdelarosa00Topic starter

  • Regular Contributor
  • *
  • Posts: 73
  • Country: mx
  • Manipulate your machine, you're a Technomancer...
Re: Program stuck with simple math operations.
« Reply #27 on: October 10, 2017, 02:08:29 am »
Was feeding "count=grad/degperstep;" wich has some implicit conversions that aren't there anymore.
Space landfill waste consultants say: "If you think you can or if you think you can't you're right" - Always on my way to be a better electronic wizard
 

Offline zdelarosa00Topic starter

  • Regular Contributor
  • *
  • Posts: 73
  • Country: mx
  • Manipulate your machine, you're a Technomancer...
Re: Program stuck with simple math operations.
« Reply #28 on: October 10, 2017, 02:12:45 am »
Yeah, someone also said that a handmade routine with a string array could be useful, but I got rid of those and I'm doing one last check if the floats cause any trouble anymore, I have no more implicits...

Can you tell me if that book you said it's hard to get? I so want to read it...

And yeah... really didn't know all this floating point mass murderers, but it really doesn't surprise me as float architecture it's always more complex.
Space landfill waste consultants say: "If you think you can or if you think you can't you're right" - Always on my way to be a better electronic wizard
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: Program stuck with simple math operations.
« Reply #29 on: October 10, 2017, 02:18:50 am »
Hey everyone, the first thing I did was to get rid of the variable procedures so a scene where only one motor is used it's now my code... (constant degrees per step and such)... I attach said code here:

This is the whole code now... (Wich still has a couple implicit nasty crap since I just read you're responses):
Wich now gets stuck in the 'atoi' func.


atoi() wants to convert from a string (an array of chars, not just a single char).  You pass it the name of the array which in C is the same as sending a pointer to the array:

char mystring[10]; // probably not long enough for floating point, dimension it to 15.
int myint;

mystring[0] = UART_Read(); // reads just one char into mystring
mystring[1] = 0; // terminate the string
myint = atoi(mystring);

 

Offline Nusa

  • Super Contributor
  • ***
  • Posts: 2416
  • Country: us
Re: Program stuck with simple math operations.
« Reply #30 on: October 10, 2017, 02:21:41 am »
Hey everyone, the first thing I did was to get rid of the variable procedures so a scene where only one motor is used it's now my code... (constant degrees per step and such)... I attach said code here:

This is the whole code now... (Wich still has a couple implicit nasty crap since I just read you're responses):
Wich now gets stuck in the 'atoi' func.


Code: [Select]
//--CONTROLADORA DE STEPPER PRECISA--
//1.-Grados?
//2.-Sentido?
//3.-Velocidad?

#include <built_in.h>

/*
NOTAS APRENDIDAS:
/No se permite compilar un retardo variable....
/"delay_us(time)" -> wrong
/Las interrupciones pueden llamarse como absolutamente se quiera mientras
tenga la denominacion IVT correcta (tabla de vectores de interrupcion)
*/

//Variables
const char right[]={0b1100,0b1100,0b0100,0b0110,0b0010,0b0011,0b0001,0b1001}; //Excitacion derecha
const char left[]={0b1001,0b0001,0b0011,0b0010,0b0110,0b0100,0b1100,0b1100}; //Excitacion izquierda
int pos; //Para controlar la posición de la excitación (1~8)
char salidas; //Pines PORTB para motor

char aa; //Para recibir de la UART
char grad, sentt, veloc; //Peticiones de datos en char
int gra,sent,velo; //Enteros

float degperstep; //->
int stepperrev, count; //Para control de ángulo

float vueltaspseg; //->
float pasosporvuelta; //->
int time; //Para control de la velocidad

int xx; //Control de flujo de cuestiones/acciones

int i,j; //For statements
//Métodos
void movermotor();

//INICIO
void main()
{
//Configuración->
//SISTEMA
W15=0x0900;    //Pila acomodada
//MÓDULOS
UART1_Init(19200); //Init&Config de la UART, 8b data, no parity, 1 stop
delay_ms(100); //Delay recomendado
//TRISB.RB2=1; //Entrada RX
RPINR18=0x05; //RP5RX, pin 14
RPOR3=0b00011; //RP6TX, pin 15
//PINES
TRISB.RB8=0;
TRISB.RB9=0;
TRISB.RB10=0;
TRISB.RB11=0; //Salidas motor

//Inicializaciones
//stepperrev=648; //<-Pasos por vuelta del motor usado.....
//648
//degperstep=360/stepperrev; //Grados por paso del motor usado....
//1.8

xx=0;//Controla el flujo de preguntas
pos=0; //Conteo de excitación
UART1_Write_Text("\n¿Cuántos grados desea girar?... (0~360°) \n");
UART1_Read(); //Limpiar para no recibir por equivocacion


//Código
while(1)
  {
  if (UART1_Data_Ready())
   {
    delay_ms(100);
    aa=UART1_Read(); //Recibimos dato
   
    switch(xx) //Flujo de preguntas
        {
        case 0: //grados
          grad=aa;
          gra=atoi(grad);
          xx++; //xx=1;
          UART1_Write_Text("¿En qué sentido desea girar?... (1-Derecha, 2-Izquierda) ");
          UART1_Read(); //Limpiar para no recibir por equivocacion
          break;
        case 1: //sentido
          sentt=aa;
          sent=atoi(sentt);
          xx++; //xx=2;
          UART1_Write_Text("¿A qué velocidad desea girar?... (uS) "); //(0~120 RPM)
          UART1_Read(); //Limpiar para no recibir por equivocacion
          break;
        case 2: //veloc
          veloc=aa;
          velo=atoi(veloc);
          movermotor();
          xx=0;
          break;
        }//fin switch
   }//End dato recibido
  }//End while
}//End main

void movermotor()
{
    /*
    int grad, sent, veloc; //Peticiones de datos en enteros
    float degperstep; //->
    int stepperrev, count; //Para control de ángulo
    float vueltaspseg; //->
    float pasosporvuelta; //->
    int time; //Para control de la velocidad
    */

    //Operaciones
    //count=grad/degperstep; //Establecer grados->cuentas (cuantos pasos vamos a avanzar)
    count=grad/1.8;
    //vueltaspseg=veloc/60; //Establecer rpm->us
    //pasosporvuelta=stepperrev*vueltaspseg;
    //pasosporvuelta=200*vueltaspseg;
    //time=((1/pasosporvuelta)*100)+1;
    time=veloc;
   
     //Acknowledgement
     UART1_Write_Text("Moviendo motor...");
     delay_ms(600);
     UART1_Read();//Limpiar

    if(sent==1) //Derecha
    {
     UART1_Write_Text("Derecha... ");
     for(i=0; i<count; i++)
     {
      if(pos==8) {pos=0;}
      pos++;
      salidas=right[pos]; //Establecemos la posición de la excitación
      Hi(LATB)=salidas; //Movemos motor
      for(j=0; j<time; j++) {delay_us(1);} //Velocidad requerida
     }//Fin pasos
    }//Fin Derecha
    if(sent==2) //Izquierda
    {
     UART1_Write_Text("Izquierda... ");
     for(i=0; i<count; i++)
     {
      if(pos==8) {pos=0;}
      pos++;
      salidas=left[pos]; //Establecemos la posición de la excitación
      Hi(LATB)=salidas; //Movemos motor
      for(j=0; j<time; j++) {delay_us(1);} //Velocidad requerida
     }//Fin pasos
    }//Fin Izquierda
    delay_ms(500);
    xx=0;//Controla el flujo de preguntas
    pos=0; //Conteo de excitación
    UART1_Write_Text("\n¿Cuántos grados desea girar?... (0~360°) \n");
    UART1_Read(); //Limpiar para no recibir por equivocacion
    return;
}//Fin movermotor()




/*--INFORMACIÓN DE CÁLCULOS--------------------------------------
/>PASOS:---------------------------------------------------------
/Ej.: Si stepper tiene 648 pasos por revolución, 648 pasos=360°
/tiene 1.8° por paso (360/648), al pedir grados, dividimos
/entre la resolución del motor (Ej.: 45/1.8=25) (x/degperstep) y
/resultará el número de pasos: 25................................
/cuenta=(grad/degperstep)    ------------------------------------
/----------------------------------------------------------------
/>TIEMPO:--------------------------------------------------------
/-La velocidad máxima son 120 RPM, (120/60=2)(vueltaspseg=vel/60)
/eso es 2 vueltas por segundo, a 648 pasos por vuelta son 1248
/pasos, (pasosporvuelta=stepperrev*vueltaspseg), en 1 segundo son
/entonces: (1/pasosporvuelta=801.28uS)(time=1/pasosporvuelta),
/time está en uS para la velocidad más alta.-------------------->
/>>SUMARIO:
/1.- vueltaspseg=vel/60 (FLOAT)
/2.- pasosporvuelta=stepperrev*vueltaspseg (FLOAT)
/3.- time=(1/pasosporvuelta*100)*100 (INT)
/Ej: 3 RPM->
/vueltaspseg=3/60 -> .05
/pasosporvuelta=648*.05 -> 32.4
/time=1/32.4 -> .03086*100 -> 30.86 -> 30 (en mS int, truncado)
/Ej. Final:
/delay_us(30); //3 RPM
/delay_us(801280); //120 RPM (vel máx)
/----------------------------------------------------------------
/----------------------------------------------------------------*/

The atoi() function typically takes a STRING as an argument and returns an INT. A string, by convention, is zero-terminated. That means the last char of the string needs to be a 0.
You're trying to pass a single character as an argument, not a valid string.

This might help:
https://www.tutorialspoint.com/c_standard_library/c_function_atoi.htm
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: Program stuck with simple math operations.
« Reply #31 on: October 10, 2017, 02:22:33 am »

Can you tell me if that book you said it's hard to get? I so want to read it...


Kernighan & Ritchie?  Sure, every programmer in the world probably has a copy.  Really!

https://www.amazon.com/Programming-Language-2nd-Brian-Kernighan/dp/0131103628/ref=dp_ob_title_bk

The 2d edition is a lot more up to date with ANSI C but the 1st edition is a CLASSIC!

You can find used copies of both at Alibris.com.
 

Offline sasa

  • Regular Contributor
  • *
  • !
  • Posts: 168
  • Country: 00
  • Hobbyist in electronic
Re: Program stuck with simple math operations.
« Reply #32 on: October 10, 2017, 07:11:32 am »
This is the whole code now... (Wich still has a couple implicit nasty crap since I just read you're responses):
Wich now gets stuck in the 'atoi' func.
...

BTW, on multiple responses, it would be much clearer to quote at least one crucial line on post you reply - use "Quote" link on the message and delete excess...

As mentioned, if you use atoi() it is assumed to use null terminated string, not a char (one byte). Unless you have special application to communicate with the PIC, all data you sending from console are assumed in ASCII.

Then to convert it, only reading char by char is possible. If these are numbers only in ASCII, simply subtract 48 from it, for instance:

Code: [Select]
//gra=atoi(grad);
gra = grad - 48;

When read ASCII value for degree from 0 to 360 and you want to avoid buffer (temp string to hold data before converting with atoi() ), you can use simple function and directly read and convert it, as follows (or similar):

Code: [Select]
int UART1_DirectReadInteger(char *LastChar)
{
  /*
   * Force reading integer value, exit on any other character than '0' to '9'
   *   allowing immediate reading from UART
   *   
   * LastChar - return last read character or null-termination if no data
   *            are vailable from UART
   */
 
  int value;
  char ch;

  *LastChar = '\0';
  value = 0;

  // Endless loop, waiting data to read from UART
  while (1)
  {

    // Ensure to process data only if available   
    if (UART1_Data_Ready()) {

      ch = UART1_Read();

      // Ensure only numbers are processed     
      if (ch >= '0' && ch <= '9')
      {
        value *= 10;      // Multiple by 10
        value += ch - 48; // Convert character to number and add it
      }
      else
      {
        *LastChar = ch;
        break;
      }
    }

   // Note: Add timer logic or similar here in order to exit from endless loop
   //       if no data are available from UART
   
  }

  return value;
}

int main ()
{

  char ch;
  int degree;

  //...

  degree = UART1_DirectReadInteger(&ch);

  // Handle ch value which may be LF, CR or any other non-digit, then continue ...

}

Not an ideal function, however it may be a start to modify it or use code as you like.
« Last Edit: October 10, 2017, 09:41:11 am by sasa »
The 30+ years professional desktop software designer and software engineer
 

Offline zdelarosa00Topic starter

  • Regular Contributor
  • *
  • Posts: 73
  • Country: mx
  • Manipulate your machine, you're a Technomancer...
Re: Program stuck with simple math operations.
« Reply #33 on: October 11, 2017, 12:23:12 am »
Apparently ends with an undefined character or a null.... I did change it to "atof" and it works receiving, I'm trying now the actual logic since it got changed to almost all floats
Space landfill waste consultants say: "If you think you can or if you think you can't you're right" - Always on my way to be a better electronic wizard
 

Offline zdelarosa00Topic starter

  • Regular Contributor
  • *
  • Posts: 73
  • Country: mx
  • Manipulate your machine, you're a Technomancer...
Re: Program stuck with simple math operations.
« Reply #34 on: October 11, 2017, 12:28:41 am »
Thanks!.. Its weird the electronic version its more expensive than the paperback..
Space landfill waste consultants say: "If you think you can or if you think you can't you're right" - Always on my way to be a better electronic wizard
 

Offline zdelarosa00Topic starter

  • Regular Contributor
  • *
  • Posts: 73
  • Country: mx
  • Manipulate your machine, you're a Technomancer...
Re: Program stuck with simple math operations.
« Reply #35 on: October 11, 2017, 12:31:57 am »
Quote
When read ASCII value for degree from 0 to 360 and you want to avoid buffer (temp string to hold data before converting with atoi() ), you can use simple function and directly read and convert it, as follows (or similar):

Not an ideal function, however it may be a start to modify it or use code as you like.

I'll definatelly check that out if the new version doesn't work.. I'm using 'aotf' now! (It worked without the apparent hiccups)
Space landfill waste consultants say: "If you think you can or if you think you can't you're right" - Always on my way to be a better electronic wizard
 

Offline Nusa

  • Super Contributor
  • ***
  • Posts: 2416
  • Country: us
Re: Program stuck with simple math operations.
« Reply #36 on: October 11, 2017, 12:41:35 am »
atof() also takes a string as input. If you're still passing a char you're depending on whatever happens to be in memory after the variable declaration. Be prepared for it to suddenly break when you change the contents of some seemingly unrelated variable.
 

Offline Bruce Abbott

  • Frequent Contributor
  • **
  • Posts: 627
  • Country: nz
    • Bruce Abbott's R/C Models and Electronics
Re: Program stuck with simple math operations.
« Reply #37 on: October 11, 2017, 06:26:52 am »
I'm using 'aotf' now! (It worked without the apparent hiccups)
No compiler warnings?
 

Offline sasa

  • Regular Contributor
  • *
  • !
  • Posts: 168
  • Country: 00
  • Hobbyist in electronic
Re: Program stuck with simple math operations.
« Reply #38 on: October 11, 2017, 08:21:15 am »
I'm using 'aotf' now! (It worked without the apparent hiccups)

It may work "without the apparent hiccups", but it will return wrong result if ever find null terminated character...

Notice that both functions receive pointer to the data as a parameter and will stop working when character on which point is null terminated character, or the function itself detect something unexpected. For instance:

Code: [Select]
char deg; // only 1 byte
char buff[10]; // is  10 + 1 bytes length, where last byte is null terminated character '\0'

If you change 11th byte to something else, you will have unexpected results.

On:
strcpy(buff, "12345");  // buff will become 12345+'\0'+????+'\0'

Further:
deg = '9';

Let assume in memory map we first have deg value then buff value.
Then we will have on atoi(deg) or atof(deg) following:
912345

If there is no null-termination after '5', we will have wrong result depending on what is under that position instead '\0' and following existed data.

If there is no null-terminated character at all, application will probably hangs, give an AV or on PIC probably constantly reset.

And non of that is certainly what we expect.

BTW, "deg' variable is not a pointer and many compilers will not even compile atoi(deg) without warning, as that is parameter conflict, however MikroC may accept that construction and thread as atoi(&deg). Just speculation based on OPs explanation, I do not work personally with MikroC.
« Last Edit: October 11, 2017, 09:02:30 am by sasa »
The 30+ years professional desktop software designer and software engineer
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf