Program stuck with simple math operations. - Page 1
Forum section: electronics / general

author: zdelarosa00
author_rank: Regular Contributor
timestamp: October 09, 2017, 02:11:25 am
content: uC: dsPIC33FJ12GP202IDE and Libraries: mikroC Pro for dsPICSimulator: Proteus ISISCompiler ver.: 6.2So I have a question. I'm developing some code that communicates by UART (with library) with the computer in order to move a steppermotor 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, butI 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 wayits desired. but the code stops running in the simulation just after the data is received, and the pins that correspond to the stepper motor neverchange 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 anotherversion 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ónvueltaspseg=veloc/60; //Establecer rpm->uspasosporvuelta=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 forgetting 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 outputand 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 becausing 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 derechaconst char left[]={0b1001,0b0001,0b0011,0b0010,0b0110,0b0100,0b1100,0b1100}; //Excitacion izquierdaint pos; //Para controlar la posición de la excitación (1~8)char salidas; //Pines PORTB para motorint aa; //Para recibir de la UARTint grad, sent, veloc; //Peticiones de datos en enterosfloat degperstep; //->int stepperrev, count; //Para control de ángulofloat vueltaspseg; //->float pasosporvuelta; //->int time; //Para control de la velocidadint xx; //Control de flujo de cuestiones/accionesint 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 useson 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; //Establecemos la posición de la excitaciónHi(LATB)=salidas; //Movemos motorfor(j=0; j<time; j++) {delay_us(1);} //Velocidad requerida}//Fin pasos}//Fin Derechaelse //Izquierda{for(i=0; i<count; i++){if(pos==8) {pos=0;}pos++;salidas=left; //Establecemos la posición de la excitaciónHi(LATB)=salidas; //Movemos motorfor(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 indeedat least doing 45/1.8 and get a coherent result would be more than enough since it's the main goal of the program.

author: rstofer
author_rank: Super Contributor
timestamp: October 09, 2017, 02:44:20 am
content: 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.

author: Nusa
author_rank: Super Contributor
timestamp: October 09, 2017, 02:57:26 am
content: 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.

author: sasa
author_rank: Regular Contributor
timestamp: October 09, 2017, 03:38:51 am
content: 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:if (degperstep!=0)count=(grad/degperstep);elsecount=0;pos=0;time = 6000 / (stepperrev*veloc) + 1;

author: NorthGuy
author_rank: Super Contributor
timestamp: October 09, 2017, 03:56:47 am
content: Code:vueltaspseg=veloc/60; //Establecer rpm->uspasosporvuelta=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.

author: Bruce Abbott
author_rank: Frequent Contributor
timestamp: October 09, 2017, 04:21:05 am
content: Quote from: zdelarosa00 on October 09, 2017, 02:11:25 amSo it locks up inside 'count=(grad/degperstep)'?QuoteFloating 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:int decdegperstep = 18; // degrees per step * 10count = (grad*10)/decdegperstep;

author: JPortici
author_rank: Super Contributor
timestamp: October 09, 2017, 05:04:57 am
content: 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 manualthird, 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 numbersI 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 accuracyfifth 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

author: rstofer
author_rank: Super Contributor
timestamp: October 09, 2017, 02:56:47 pm
content: 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.

author: sasa
author_rank: Regular Contributor
timestamp: October 09, 2017, 05:14:40 pm
content: Quote from: rstofer on October 09, 2017, 02:56:47 pmWhen division by zero is attempted, operation should be stopped and divide by zero trap should be generated.

author: JPortici
author_rank: Super Contributor
timestamp: October 09, 2017, 07:17:52 pm
content: 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

author: rstofer
author_rank: Super Contributor
timestamp: October 09, 2017, 08:08:20 pm
content: 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!

author: sasa
author_rank: Regular Contributor
timestamp: October 09, 2017, 09:04:47 pm
content: There is nothing to speculate about, everything is explained by Microchip:http://ww1.microchip.com/downloads/en/DeviceDoc/70189C.pdf

author: zdelarosa00
author_rank: Regular Contributor
timestamp: October 10, 2017, 01:12:36 am
content: 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 eitherUART1_Write(); //Wich to my understanding sends an unformatted byte, and...UART1_Write_Text("Wich sends a string");

author: zdelarosa00
author_rank: Regular Contributor
timestamp: October 10, 2017, 01:16:24 am
content: 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(?)).

author: zdelarosa00
author_rank: Regular Contributor
timestamp: October 10, 2017, 01:22:01 am
content: 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.

author: zdelarosa00
author_rank: Regular Contributor
timestamp: October 10, 2017, 01:24:38 am
content: 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...

author: rstofer
author_rank: Super Contributor
timestamp: October 10, 2017, 01:25:39 am
content: Quote from: zdelarosa00 on October 10, 2017, 01:12:36 amSuppose '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'.QuoteThere 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.

author: zdelarosa00
author_rank: Regular Contributor
timestamp: October 10, 2017, 01:27:34 am
content: 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.

author: zdelarosa00
author_rank: Regular Contributor
timestamp: October 10, 2017, 01:41:04 am
content: 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

author: zdelarosa00
author_rank: Regular Contributor
timestamp: October 10, 2017, 01:43:22 am
content: 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

author: zdelarosa00
author_rank: Regular Contributor
timestamp: October 10, 2017, 01:45:05 am
content: 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..

author: zdelarosa00
author_rank: Regular Contributor
timestamp: October 10, 2017, 01:47:22 am
content: 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...

author: zdelarosa00
author_rank: Regular Contributor
timestamp: October 10, 2017, 01:49:14 am
content: 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

author: zdelarosa00
author_rank: Regular Contributor
timestamp: October 10, 2017, 01:51:53 am
content: 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...

author: zdelarosa00
author_rank: Regular Contributor
timestamp: October 10, 2017, 01:57:51 am
content: 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://--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 mientrastenga la denominacion IVT correcta (tabla de vectores de interrupcion)*///Variablesconst char right[]={0b1100,0b1100,0b0100,0b0110,0b0010,0b0011,0b0001,0b1001}; //Excitacion derechaconst char left[]={0b1001,0b0001,0b0011,0b0010,0b0110,0b0100,0b1100,0b1100}; //Excitacion izquierdaint pos; //Para controlar la posición de la excitación (1~8)char salidas; //Pines PORTB para motorchar aa; //Para recibir de la UARTchar grad, sentt, veloc; //Peticiones de datos en charint gra,sent,velo; //Enterosfloat degperstep; //->int stepperrev, count; //Para control de ángulofloat vueltaspseg; //->float pasosporvuelta; //->int time; //Para control de la velocidadint xx; //Control de flujo de cuestiones/accionesint i,j; //For statements//Métodosvoid movermotor();//INICIOvoid main(){//Configuración->//SISTEMAW15=0x0900; //Pila acomodada//MÓDULOSUART1_Init(19200); //Init&Config de la UART, 8b data, no parity, 1 stopdelay_ms(100); //Delay recomendado//TRISB.RB2=1; //Entrada RXRPINR18=0x05; //RP5RX, pin 14RPOR3=0b00011; //RP6TX, pin 15//PINESTRISB.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.8xx=0;//Controla el flujo de preguntaspos=0; //Conteo de excitaciónUART1_Write_Text("\n¿Cuántos grados desea girar?... (0~360°) \n");UART1_Read(); //Limpiar para no recibir por equivocacion//Códigowhile(1){if (UART1_Data_Ready()){delay_ms(100);aa=UART1_Read(); //Recibimos datoswitch(xx) //Flujo de preguntas{case 0: //gradosgrad=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 equivocacionbreak;case 1: //sentidosentt=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 equivocacionbreak;case 2: //velocveloc=aa;velo=atoi(veloc);movermotor();xx=0;break;}//fin switch}//End dato recibido}//End while}//End mainvoid movermotor(){/*int grad, sent, veloc; //Peticiones de datos en enterosfloat degperstep; //->int stepperrev, count; //Para control de ángulofloat 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;//AcknowledgementUART1_Write_Text("Moviendo motor...");delay_ms(600);UART1_Read();//Limpiarif(sent==1) //Derecha{UART1_Write_Text("Derecha... ");for(i=0; i<count; i++){if(pos==8) {pos=0;}pos++;salidas=right; //Establecemos la posición de la excitaciónHi(LATB)=salidas; //Movemos motorfor(j=0; j<time; j++) {delay_us(1);} //Velocidad requerida}//Fin pasos}//Fin Derechaif(sent==2) //Izquierda{UART1_Write_Text("Izquierda... ");for(i=0; i<count; i++){if(pos==8) {pos=0;}pos++;salidas=left; //Establecemos la posición de la excitaciónHi(LATB)=salidas; //Movemos motorfor(j=0; j<time; j++) {delay_us(1);} //Velocidad requerida}//Fin pasos}//Fin Izquierdadelay_ms(500);xx=0;//Controla el flujo de preguntaspos=0; //Conteo de excitaciónUART1_Write_Text("\n¿Cuántos grados desea girar?... (0~360°) \n");UART1_Read(); //Limpiar para no recibir por equivocacionreturn;}//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)/----------------------------------------------------------------/----------------------------------------------------------------*/

author: NorthGuy
author_rank: Super Contributor
timestamp: October 10, 2017, 02:02:59 am
content: Quote from: zdelarosa00 on October 10, 2017, 01:45:05 amWhat values are you feeding to this routine?

author: rstofer
author_rank: Super Contributor
timestamp: October 10, 2017, 02:03:15 am
content: Quote from: zdelarosa00 on October 10, 2017, 01:45:05 amWhat 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.

author: zdelarosa00
author_rank: Regular Contributor
timestamp: October 10, 2017, 02:08:29 am
content: Was feeding "count=grad/degperstep;" wich has some implicit conversions that aren't there anymore.

author: zdelarosa00
author_rank: Regular Contributor
timestamp: October 10, 2017, 02:12:45 am
content: 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.

author: rstofer
author_rank: Super Contributor
timestamp: October 10, 2017, 02:18:50 am
content: Quote from: zdelarosa00 on October 10, 2017, 01:57:51 amatoi() 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; // probably not long enough for floating point, dimension it to 15.int myint;mystring = UART_Read(); // reads just one char into mystringmystring = 0; // terminate the stringmyint = atoi(mystring);

author: Nusa
author_rank: Super Contributor
timestamp: October 10, 2017, 02:21:41 am
content: Quote from: zdelarosa00 on October 10, 2017, 01:57:51 amThe 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

author: rstofer
author_rank: Super Contributor
timestamp: October 10, 2017, 02:22:33 am
content: Quote from: zdelarosa00 on October 10, 2017, 02:12:45 amKernighan & 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_bkThe 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.

author: sasa
author_rank: Regular Contributor
timestamp: October 10, 2017, 07:11:32 am
content: Quote from: zdelarosa00 on October 10, 2017, 01:57:51 amBTW, 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://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: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 UARTwhile (1){// Ensure to process data only if availableif (UART1_Data_Ready()) {ch = UART1_Read();// Ensure only numbers are processedif (ch >= '0' && ch <= '9'){value *= 10; // Multiple by 10value += 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.

author: zdelarosa00
author_rank: Regular Contributor
timestamp: October 11, 2017, 12:23:12 am
content: 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

author: zdelarosa00
author_rank: Regular Contributor
timestamp: October 11, 2017, 12:28:41 am
content: Thanks!.. Its weird the electronic version its more expensive than the paperback..

author: zdelarosa00
author_rank: Regular Contributor
timestamp: October 11, 2017, 12:31:57 am
content: QuoteI'll definatelly check that out if the new version doesn't work.. I'm using 'aotf' now! (It worked without the apparent hiccups)

author: Nusa
author_rank: Super Contributor
timestamp: October 11, 2017, 12:41:35 am
content: 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.

author: Bruce Abbott
author_rank: Frequent Contributor
timestamp: October 11, 2017, 06:26:52 am
content: Quote from: zdelarosa00 on October 11, 2017, 12:31:57 amNo compiler warnings?

author: sasa
author_rank: Regular Contributor
timestamp: October 11, 2017, 08:21:15 am
content: Quote from: zdelarosa00 on October 11, 2017, 12:31:57 amIt may work "without the apparent hiccups", but it will return wrong result if ever find null terminated character...Notice that both functions receivepointerto 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:char deg; // only 1 bytechar buff; // 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:912345If 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.