2025. december 23., kedd

Log No.3 of the 25/26 Hungarian National Engineering Olympiad

 


Okay, so I don't really have enough new material to make this blog post, but I'm experiencing some of the weirdest errors and behavior from my python code that gets Serial input and passes it to a string parsing C++ exe. I SHOULD be debugging it but I'm so flabbergasted that I have to share this right now.

But before that, I mentioned in my last blog how I was trying to rewrite the PIC code to make it shorter by like ~150 lines, but couldn't do that because I didn't know how to increment binary. Well, as it turns out, its literally just that. uint8_t Var = 0b00000 and then Var++. That's it, the MCU can handle it. Really tried to overcomplicate that one. Anyways, I managed to go from writing this code out 15 times

    ADCON0bits.CHS = 0b00000; //Select AN0
    __delay_ms(3); //Delay for channel switching
    ADCON0bits.GO_nDONE = 1; //Start sampling
    while(ADCON0bits.GO_nDONE == 1){ //Wait until sampling is done.
        
    }
    A0result = ((uint16_t)ADRESH << 8) | ADRESL;

to this:

    uint16_t results[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};    
    uint8_t ChSEL = 0b00000;
    char label[6];   // "A14:\0"
    label[0] = 'A';
    
    while(1){
        for(int i = 0; i <= 14; i++){
            ADCON0bits.CHS = ChSEL; //Select Channel
            __delay_ms(3); //Delay for channel switching
            ADCON0bits.GO_nDONE = 1; //Start sampling
            while(ADCON0bits.GO_nDONE == 1){ //Wait until sampling is done.

            }
            results[i] = ((uint16_t)ADRESH << 8) | ADRESL;
            
            if (ChSEL < 10) {
                label[1] = '0';
                label[2] = '0' + ChSEL;
                label[3] = ':';
                label[4] = '\0';
            } else {
                label[1] = '0' + (ChSEL / 10);
                label[2] = '0' + (ChSEL % 10);
                label[3] = ':';
                label[4] = '\0';
            }

            dectohex(results[i], label);
              ChSEL++;
    
        }
        ChSEL = 0b00000;
       __delay_ms(950);

    }
}

Much cleaner, I'd argue. 
Another thing I want to somehow rewrite, is that, currently, the ADC values get passed to UART (dectohex function) as hex codes, so it has to get decoded at the receiving computer. Which is fine, it's not that resource-intensive to turn hex to integers (CPUs like bitshifting), but it's still inconvenient. I've been using HEX because it's easier to handle as a string (well, more accurately, as an array of chars because it's C), as it doesn't need typecasting binary->int->char. But I would like to fix that and have the ADC values passed as integers so it doesn't need decoding from hex.

SECONDLY.
I tried using Windows API to get the serial input to display the data in the OpenApollo GUI, because it's low-level C and runs fast. But working with Windows API makes me want to commit unspeakable acts (I swear, this OS is held together by 30 year-old duct tape. Like DWORD is a 32bit integer because we REEALLYY need backwards compatibility to windows 98). So I gave up on that because python is fast enough.
Getting serial is easy enough, and I'm using subprocess to pass that data to the .exe. Right now, I'm only running some test script

int main() {
    std::string a;
    std::getline(std::cin, a);
    std::cout << "Hello World from C++. Got:" << a << std::endl;
    return 0;
}
//I don't like using namespace for std so I see what is std library
and I'm getting a multitude of really weird errors from python. Here's the incomplete list (I'm using subprocess.Popen):
I get the data from serial but it can't pass it because they're bytes, and it needs string. Fine. Easy fix.
    data = ser.readline().decode('ascii', errors='ignore')
Then I write this:
    AnalogParse.stdin.write(data)
It gives me a ValueError of: I/O operation on closed file. 
SO I change it to this
    data = ser.readline().decode(encoding='ascii')
No error. I don't know why, but let's move on. I need this line:
    AnalogParse.stdin.flush()
    AnalogParse.stdin.close()
And... it doesn't recognize the flush command? It did when I was running a test.py to figure out subprocess. It points to the parentheses with 'Invalid argument'. But flush() does NOT TAKE ARGUMENTS. With OS error 22: The device does not recognize the command.
Thanks Windows, very helpful.
Also this: Exception ignored in: <_io.TextIOWrapper name=3 encoding='cp1252'>
So I remove it. Now, I get the same error with
    AnalogParse.stdin.close()
Sure, I'Il remove it, I don't need it inside the loop (I think).
I had some more errors with 'I/O operation on closed file' on the flush, but I can't recreate it so I'Il just try to remember the situation.
Because of this error, I added this line
print(type(AnalogParse.stdin.flush))
And I get:
<class 'builtin_function_or_method'>
So this has absolutely NOTHING to do with I/O
But fine, I'Il import io. Still the same error, still the same type.
I remove everything unnecessary. Now, the code does run. But it gives me empty lines. The terminal opens, and it tries to write, but it just keeps writing empty lines forever. And then, after a while, it exits because of this line:
    AnalogParse.stdin.write(data)
with 'data' being an invalid argument.  I just cannot figure out why. Here's the code so far
import serial
import subprocess

ser = serial.Serial(
    port='COM4',
    baudrate=9600,
    parity=serial.PARITY_ODD,
    stopbits=serial.STOPBITS_TWO,
    bytesize=serial.SEVENBITS
)

AnalogParse = subprocess.Popen(
    ["ParseLocation.exe"],
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    text=True,
    shell = True
    )

while(True):
    data = ser.readline().decode(encoding='ascii')
    AnalogParse.stdin.write(data)
    print(AnalogParse.stdout.readline())
I do not understand.
On a side note, I also tried to remove shell=true and give it a local route, because shell adds a lot of overhead, but it just can't find it, even if I add the full C:\ path.

That's all for now.

Tamás Zétény Tóth
TTZ 

*at the PIC section, I meant float instead of int, but you get it.
 
Update: It's 4 months later, and in hindsight, these errors aren't quite deserving of the title "some of the weirdest errors and behavior". But in my defense, my main language is C++, and at the time, I hadn't used a lot of python, I got into it because of OpenApollo.

Nincsenek megjegyzések:

Megjegyzés küldése

Log No.6 of the 25/26 Hungarian National Engineering Olympiad

 Damn. A lot longer than I wanted, but I honestly forgot about this blog. So, the PCB arrived in about mid-February, if I'm not mistaken...