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

0 Members and 1 Guest are viewing this topic.

Offline zdelarosa00Topic starter

  • Regular Contributor
  • *
  • Posts: 73
  • Country: mx
  • Manipulate your machine, you're a Technomancer...
Program stuck with simple math operations.
« on: October 09, 2017, 02:11:25 am »
uC: dsPIC33FJ12GP202
IDE and Libraries: mikroC Pro for dsPIC
Simulator: Proteus ISIS
Compiler ver.: 6.2

So I have a question. I'm developing some code that communicates by UART (with library) with the computer in order to move a stepper
motor with precision, so by starting the program it asks for 1.-Direction (Left/Right). 2.-Degrees(0-360). 3.-Speed(0-120rpm max).

And by this point everything works, I managed to configure everything, dave the data and get the code structure in order, but
I have one issue..

When the UART finishes receiving the correct data, it calls a function in order to manipulate the data it got, and move the stepper motor the way
its desired. but the code stops running in the simulation just after the data is received, and the pins that correspond to the stepper motor never
change state, (said motor is conected throught a L298N H-Bridge controller).

Now, I have used that motor driver and said logic before, so first, as I didn't have experience with C fuctions, I made another
version of the program that gets rid of the function for troubleshooting and after doing that I reduced the problem to this secion of code:

//"Problematic section"------------------------------
    count=(grad/degperstep); //Establecer grados->cuentas (cuantos pasos vamos a avanzar)
    pos=0; //Conteo de excitación
    vueltaspseg=veloc/60; //Establecer rpm->us
    pasosporvuelta=stepperrev*vueltaspseg;
    time=((1/pasosporvuelta)*100)+1;
//End of section---------------------------------------

Note: Certain operations have what I consider an implicit trunk, like ones "int=float/int" or such, this for
getting those variables to take part in the variable delays in the for loop and such.

Now it's not inside a function, so calling and receiving the correct data was not the problem, now, when I try to debug inside mikroC,
it stops right in the first instruction of that block of code and gets to a routine so called "long2float" that never gets out of.

So, after trying to eliminate the need for calculations, I set the variables "count", "time", and "pos" to see if I have and output
and voilá, I have an output to the motor, so, my question is:

->Are those calculations too complex to do for the microcontroller or am I running out of memory? I can't very much understand what could be
causing the issue since this microcontrollers are supossed to have pretty strong RAM and math power.

Now this are my variables and the type they are:

//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
int aa; //Para recibir de la UART

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

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

int i,j; //For statements
//----------------------------------------------

I haven't tried changing them all to one type (all float/all int) but that would really mess the process and I have change one or two (the ones that it uses
on the first line of calculations, for example)
so I doubt that really solves anything.

The following code is the moving routine and I have succesfully implemented it in the past for moving said motor:

//Start of the routine---------------------------------
if(sent==1) //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
    else //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
//End of move motor routine-----------------------------

I need the variable times and degrees for the cas when another motor with different specifications is used.

The compiler gives no errors and evreything works but the section I give.

How can I approach to solve this issue?, precision with variables is not a problem (I don't need 10 decimals in anything) but indeed
at least doing 45/1.8 and get a coherent result would be more than enough since it's the main goal of the program.
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 #1 on: October 09, 2017, 02:44:20 am »
First of all, I would explicitly cast everything!
Second, I would make liberal use of printf() and send via UART all the intermediate and final results.
Third, I would create a dummy program to exercise just the math and casting.  Printf() everything.
 

Offline Nusa

  • Super Contributor
  • ***
  • Posts: 2416
  • Country: us
Re: Program stuck with simple math operations.
« Reply #2 on: October 09, 2017, 02:57:26 am »
You're mixing floats and ints and making assumptions that the operation will be a floating operation, when in fact you may be getting some integer operations. No surprise you're getting unexpected results. Make everything explicit and you'll probably get better results. Also, your time equation could be simplified....the multiply is not necessary.
 

Offline sasa

  • Regular Contributor
  • *
  • !
  • Posts: 168
  • Country: 00
  • Hobbyist in electronic
Re: Program stuck with simple math operations.
« Reply #3 on: October 09, 2017, 03:38:51 am »
As well, ensure possible division by zero is handled:
degperstep: count=(grad/degperstep)
pasosporvuelta: time=((1/pasosporvuelta)*100)+1;

Following will always return false result:
time=((1/pasosporvuelta)*100)+1;

Instead:
time=((1.0/pasosporvuelta)*100)+1;

Common misunderstanding how implicit conversion works in C. There is no need to cast everything, just crucial parts in expression.

I will not going into correctness of time formula, however you can use integer arithmetic here avoding all implicit conversions. The whole critical section may look as follows:

Code: [Select]
if (degperstep!=0)
  count=(grad/degperstep);
else
  count=0;

pos=0;
time = 6000 / (stepperrev*veloc) + 1;
« Last Edit: October 09, 2017, 03:53:35 am by sasa »
The 30+ years professional desktop software designer and software engineer
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3146
  • Country: ca
Re: Program stuck with simple math operations.
« Reply #4 on: October 09, 2017, 03:56:47 am »
Code: [Select]
vueltaspseg=veloc/60; //Establecer rpm->us
pasosporvuelta=stepperrev*vueltaspseg;
time=((1/pasosporvuelta)*100)+1;

"veloc" is integer. If it is ever less than 60, "vueltaspseg" will be zero, which will cause division by zero when calculating "time".

There's no need to mix floats and integers. Either do everything in floats, or, if it is too slow, do everything in integers. However, switching to integers will require more work, such as finding the correct scale etc.
 

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 #5 on: October 09, 2017, 04:21:05 am »
I reduced the problem to this secion of code:

//"Problematic section"------------------------------
    count=(grad/degperstep); //Establecer grados->cuentas (cuantos pasos vamos a avanzar)
...

when I try to debug inside mikroC, it stops right in the first instruction of that block of code and gets to a routine so called "long2float" that never gets out of.
So it locks up inside 'count=(grad/degperstep)'?

Quote
->Are those calculations too complex to do for the microcontroller or am I running out of memory? I can't very much understand what could be causing the issue since this microcontrollers are supossed to have pretty strong RAM and math power.
Floating point operations can take a lot of memory and CPU power. The dsPIC33FJ12GP202 is plenty powerful enough, but only has 12kB (8k Words) of ROM and 1kB RAM.

Try to use integers wherever practicable. When calculations involve fractional values, temporarily scale the numbers up until they become integers. To maintain accuracy do multiplications first and divisions last. For example if the step angle is 1.8º, do:-

Code: [Select]
  int decdegperstep = 18; // degrees per step * 10
  count = (grad*10)/decdegperstep;


 

Offline JPortici

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
Re: Program stuck with simple math operations.
« Reply #6 on: October 09, 2017, 05:04:57 am »
Please read both the programmer's manual (to understand the architecture and eventually how to write assembly routines) and the compiler manual, to see how to use the whole instruction set and eventually how to write assembly.

First thing, the dspic CAN perform a 32bit by 16 bit integer division with dedicated instructions in 19 clock cycles, but due to the nature of the algorythm it can't detect overflows. For this reason XC16 will perform a division by excecuting a software routine which can be many times slower ( i think it was in the order of 400 cycles) unless you tell the compiler to explicitely use the division instructions, by using a _builtin routine (but beware of the overflows, do it only when you are 100 percent certain that it won't overflow... for example if your divisor is a fixed number you can check if the divident is lower than X and in case use the hardware division)

I assume that MikroC is the same (I only used the dspic version with a 30f many years ago, so i don't know.)

Same thing if you want to use the 40bit dsp. it can operate with integers or fixed point numbers, but you have to understand how it works, where to place your variables in memory and such. 33FJ has a sligtly different implementation of the DSP than the 33EP so you should again check the programmer's manual and the compiler manual

third, in any case divisions take always a lot of time so unless you have the power or the time to crunch numbers, if you can do them elsewhere and either send the result or send a reciprocal and perform a multiplication instead (which takes one clock cycle for a 16x16bit multiplication).

fourth, as other said, don't mix floats with ints, and this MCU doesn't have hardware floating point and the conversion between the two always take time. you should keep using INTs or fixed point numbers
I don't think there's need to use floats, i'd just scale everything too (multiply by 10,20,60,100, ..) so they become integer numbers with sufficient accuracy

fifth and last as other said (but it's better to stress it out) you have many cases where you may be able to perform a division by zero, either by accident or by a result of calculations. you must add a check so that if any of the dividers is zero they are changed to something else, like 1. the behaviour of a division by zero is usually a math trap you have to address unless you want your MCU to reset
« Last Edit: October 09, 2017, 05:11:15 am by JPortici »
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: Program stuck with simple math operations.
« Reply #7 on: October 09, 2017, 02:56:47 pm »
Given that there is so little RAM, what is the possibility that the heap and stack are colliding?  It would be interesting to see the RAM map from the linker.  If there is no heap, what about the stack colliding with allocated RAM?

In addition to the other problems noted earlier.

Getting the wrong answer, even dividing by zero shouldn't cause the uC to halt.  But a stack collision will almost always result in something going seriously wrong.
 

Offline sasa

  • Regular Contributor
  • *
  • !
  • Posts: 168
  • Country: 00
  • Hobbyist in electronic
Re: Program stuck with simple math operations.
« Reply #8 on: October 09, 2017, 05:14:40 pm »
Getting the wrong answer, even dividing by zero shouldn't cause the uC to halt.

When division by zero is attempted, operation should be stopped and divide by zero trap should be generated.
« Last Edit: October 09, 2017, 05:19:16 pm by sasa »
The 30+ years professional desktop software designer and software engineer
 

Offline JPortici

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
Re: Program stuck with simple math operations.
« Reply #9 on: October 09, 2017, 07:17:52 pm »
as i said, a division by zero generates a math trap and sets the division by zero flag (Bit 6 of INTCON1).

I don't know how mikroC handles traps that don't have their explicit handler, but i would bet it either reset the MCU (and the debugger halts there) or it is stuck in a while(1) unless you write the routine
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: Program stuck with simple math operations.
« Reply #10 on: October 09, 2017, 08:08:20 pm »
Right, division by zero generates an arithmetic trap.  I have no idea where the trap vector branches nor what the handler code would do.  I wouldn't bet on 'hang' because that is just all wrong for an embedded system.  One bad sensor reading and the train goes off the track because the uC froze up.  I would hope that it would just deliver either a maximum result or zero but I wouldn't bet on it.

Or, maybe the user is suppose to write the trap code.  That would be a sensible choice.  But what to do?  The embedded system is supposed to keep running so just return zero and leave it up to the user to check the flags?

It is better to avoid dividing by zero in the first place.  Even then, what to do about a zero divisor?  Something else is wrong.

Check the documentation!
 

Offline sasa

  • Regular Contributor
  • *
  • !
  • Posts: 168
  • Country: 00
  • Hobbyist in electronic
Re: Program stuck with simple math operations.
« Reply #11 on: October 09, 2017, 09:04:47 pm »
There is nothing to speculate about, everything is explained by Microchip:

http://ww1.microchip.com/downloads/en/DeviceDoc/70189C.pdf
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 #12 on: October 10, 2017, 01:12:36 am »
I'm sorry, there's a couple things i'm not familiar with and almost sound like they're all software... What's the concept of 'casting' everything?... Also I'm using the UARTx library from the mikroC compiler and there's no such function as 'printf()', there's either

UART1_Write(); //Wich to my understanding sends an unformatted byte, and...
UART1_Write_Text("Wich sends a string");
 \$\Omega\$
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 #13 on: October 10, 2017, 01:16:24 am »
You're right, I didn't think of doing everything in floats, but for example there's a little routine where a for loop goes on a count of every step excitation that the motor has to do, what when the loop 'i' variable compares "i<56.789" for example? Does that affect the process of the loop of the compiler will try?, technically there could be a case where 'i' reaches from 56 to 57 and would be "i<56.786=FALSE", but that's just human thinking, I'm not sure how the compiler handles this kind of stuff (plus on the top of my head, 'i' is an integer here, wich could be more implicit conversions(?)) :-/O.
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 #14 on: October 10, 2017, 01:22:01 am »
Well, you've got a good point, with the divide by zero, but my 'degperstep' variable is a constant for when manipulating another types of motors, wich you change and compile before you use, mine just happens to be the classic 1.8º/step, wich I'm sorry I'm not sure I included in my original post, so I think that could be omitted...

Now, the part with the time formula seems interesting, I think I can actually make a "time=(100/pasosporvuelta)+1;" to loose some steps, also, that eventually ends up as a uS count in a delay so I thought I had it covered against zero with the "+1" part, since I can only use either 'delay_ms' or 'delay_us' so I came up with something that covers the minimum time cases wich aren't even 1mS between steps. :-/O
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 #15 on: October 10, 2017, 01:24:38 am »
Thanks!, I didn't know such thing!... Those implicit conversions where the ones I have so much doubt about, now.. How safe is everything floats?, as in a compare variable for the for loops, for example?, I don't find this compiler to be very good at troubleshooting freezes...
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 #16 on: October 10, 2017, 01:25:39 am »
I'm sorry, there's a couple things i'm not familiar with and almost sound like they're all software... What's the concept of 'casting' everything?... Also I'm using the UARTx library from the mikroC compiler and there's no such function as 'printf()', there's either


Suppose 'i' and 'j' are integers and 'x' is a float and I want an integer result:

i = (int) ((float) j / x));

'j will be converted to a float and divided by 'x' which is already a float.  The result will be converted to an integer and stored in 'i'.

Quote

UART1_Write(); //Wich to my understanding sends an unformatted byte, and...
UART1_Write_Text("Wich sends a string");
 \$\Omega\$

There are probably functions that convert a numeric value (integer or float) to a string.  In C, itoa() converts an integer to an ascii string.  Similarly, ftoa() converts a float to a string.  Google for them.  Just do the conversion into a character buffer (array of chars) and use UART1_Write_Text(mystring) to print the results.  Make sure the buffer is long enough.

Different libraries implement these functions in slightly different ways.  Check your documentation.
« Last Edit: October 10, 2017, 01:43:20 am by rstofer »
 

Offline zdelarosa00Topic starter

  • Regular Contributor
  • *
  • Posts: 73
  • Country: mx
  • Manipulate your machine, you're a Technomancer...
Re: Program stuck with simple math operations.
« Reply #17 on: October 10, 2017, 01:27:34 am »
Yes, in simulation, apparently phisically, and inside debugging (doesn't stop but enters an assembler loop)...

That integer trick really seems to have sense... Am I really into danger of running out of memory with those operations?, I'm not sure if this IDE has some device estimation beyond what my code takes in kB.
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 #18 on: October 10, 2017, 01:41:04 am »
No need for checking the math architecture right now, also don't have that much time, I will try and use the scaled floats, and double check my math... I think its clear the uC can handle it so it's obviously down to my code... Thanks
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 #19 on: October 10, 2017, 01:43:22 am »
How serious?... I think this compiler takes for granted a lot of things, so memory is taking part in this discussion... But I do think is down to my code... I can't do much  better on doing the calculations before, but I can save a little instructions... Also, how wrong can that collisions go?, it's definatelly freezing but it's working just fine still... So I think it's healthy  :-DMM
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 #20 on: October 10, 2017, 01:45:05 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..
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 #21 on: October 10, 2017, 01:47:22 am »
Sure, I'm not polished enough in this compiler... But I'm sorry everyone is touching in that topic now... As far as the variable quantities go here... None of those return zero... At least the only one who implicitly does is the one who does 'int=int/float' where the second int can be smaller than the float...
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 #22 on: October 10, 2017, 01:49:14 am »
I had my share with interrupt knowledge, I think in this case is better to fix the code for avoiding the trap than to elaborate on the solution for the given trap
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 #23 on: October 10, 2017, 01:51:53 am »
Hi... Yeah.. .I'm past that issue already, thanks... I checked the documentation and am using a function now that is called 'atoi' wich does char->int, but guess what? It's stuck there now just after the UART reading that gets said char in the first place...
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 #24 on: October 10, 2017, 01:57:51 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)
/----------------------------------------------------------------
/----------------------------------------------------------------*/

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 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