Completed: / exercises

FAQ: Answers to Questions and Feedback

On this page, we answer the questions and comments raised in the feedback regarding the C language section of the course, divided by lecture chapters.

About Completing the Course

Q: I couldn’t finish the course last year. Do I need to start from scratch?
A: No. The course completions for JTKJ and/or TKJ courses are valid for one year, so you only need to complete the missing modules. However, you need to complete the entire module: Module 1, Module 2, Module 3 and/or Module 4.
Q: What exactly does the exercise deadline mean?
A: Points towards the final grade are awarded for exercises from lecture chapters 1-12 that are completed by the deadline. These exercises can be found on the Exercise subpages of the course materials. Introductory or ungraded lecture tasks within the materials do not contribute to the grade.
Q: Will I be penalized in the exercises if I attempt the same task multiple times?
A: No, you won’t. You can attempt each task as many times as needed. You get points when the checker approves your answer. However, we do not recommend using Lovelace as a C language error checker... it’s better to ask the assistants. There is only one exception. There are some questions that limit the number of answer. If you exceed the limit, your exercise wont be evaluated.
Q: The schedule for the lab session week doesn’t work for me at all!
A: Discuss this with the course staff. Without attending the lab, you won’t be able to get the development board.
Q: Can I complete the project with Arduino or other platform?
A: Generally, no. However, if you have built an embedded system as a hobby or something similar using Arduino or a similar platform, you can propose it, and we will see if it meets the course project requirements.
Q: As a minor subject student (or equivalent), I am simultaneously taking the Elementary Programming course and the JTKJ course. I’m struggling with the JTKJ tasks because they require knowledge that hasn’t yet been covered in the Elementary Programming course.
A: The Elementary Programming course is a prerequisite for JTKJ. The courses are not designed to be taken at the same time, and the course materials are not synchronized. The course instructors have no control over this, so please give feedback to those responsible for your studies.
Q: I do not live in Oulu. Can I take the course remotely?
A: The course is part of an in-person degree program, and attendance may be required for mandatory events such as laboratory exercises or final meetings. Depending on the situation, the course staff may offer alternatives, but these are provided on a case-by-case basis and are not guaranteed (exceptions are generally denied). In any case, the student must arrange to acquire the development platform themselves. Under no circumstances will we post any of the equipment.

About Lovelace

Q: The checker program keeps crashing.
A: We are very interested in hearing about this. Could you please show us during the lab or send a message explaining exactly how the crash occurs? Please include the URL of your submission.
When you receive a JSONDecodeError in Lovelace, it usually means that you have memory problems in your code (basically, you are trying to use memory positions that you are not supposed to use, e.g., overflow). In that case, the checker will kill the process. Check your loops carefully and make sure you are not trying to read/modify array positions outside their limits.
There is absolutely nothing we can do if the checker crashes due to your submission violating memory limits. It is impossible to retrieve anything from the checker because the OS kills the entire process stack immediately when you try to access memory outside of your reserved area. If you get a "checker crashed" report, your program likely has this issue.
Q: I submitted feedback, but I haven’t heard anything since. What’s wrong?
A: Feedback is shown to us anonymously, so we don’t know who to contact. We don’t publish solutions to the exercises, at least not until after the deadline.

C Language Exercises (Module 1)

Codeblocks

Q: When I try to compile/run my code in Codeblocks, I get this message: ''undefined reference to 'WinMain'
A:
Check that the main function is implemented.
Check that the main function is only in one file.
Ensure that you have created a "Console application" project, not a "Windows GUI".
Restart Codeblocks.

3. Bits and Number Systems

Q: I get frustrated with number system conversions and bit operations... and hey!, calculators exist!
A: These are such fundamental skills for a computer/electrical engineer that you should really be able to do them in your head.
Q: How can I represent a binary number in C? I saw the prefix 0b used online.
A: The prefix 0b is not standard C but an extension in some compilers. In the gcc compiler used in this course, it is working.
Binary numbers can easily be represented as hexadecimal; see the lecture materials.
Q: In hexadecimal, negative numbers usually have a minus (-) sign instead of the higher bits like 8(0b1000) and above.
A: That's true, you can use the minus sign with hexadecimal numbers as well. However, the computer internally handles these negative hexadecimal numbers as 2’s complement values, meaning the compiler does the conversion automatically.
Note that the assignment int8_t neg = -0x81 (which seems like "two minus signs") doesn’t fit within the value range and requires a 9th sign bit, which means the 8th bit is interpreted as part of the value.
In the course, we use the 2’s complement representation. For instance, when reading the register of a peripheral device, the only way to pass both positive and negative numbers is through 2’s complement.

5. Bitwise Operations in C

Q: If we're being precise, doesn’t the operations order table at the end miss the left-to-right post-increment and post-decrement operators (++ and --)? The table seems to only show the right-to-left 'first assign, then reference' versions of the ++ and -- operators. Example:
uint8_t n = 4;
printf("%d\n", n++); // <- missing, returns 4
printf("%d\n", ++n); // returns 6
printf("%d\n", --n); // returns 5

// for some reason, ++i and --i work the same as i++ and i-- in loops?!?
for (uint8_t i; i < 10; i++) {} 
for (uint8_t i; i < 10; ++i) {} 
A: Good question, there are a few things to consider here.
1) The table is meant to describe the order of precedence by rows, with higher precedence at the top. The direction of evaluation (whether left-to-right or right-to-left) depends on the row.
Evaluation direction means that if you have multiple operators of the same precedence in one statement, in what order are they evaluated, from right to left or left to right? For operator Q: (a Q b) Q c or a Q (b Q c)? On this course, you won’t need to worry about this if you use parentheses.
2) Additionally, when using these unary operators as function parameters, be careful, as the evaluation order (binding order) is compiler-dependent. This is discussed in the textbook (Kernighan & Ritchie, section 2.12).
// Here, we don’t know which operation happens first, ++ or pow()
printf("%d %d", ++n, pow(2,n));
// A clearer way to do this would be (for example)
++n;
printf("%d %d", n, pow(2,n));
3) Finally, in a for-loop, the assignment operation always comes last. So it doesn’t matter whether you use ++ before or after, as it will always be executed at the end of the iteration.

7. Control Structures in C

Q: I can't print 64-bit numbers with printf. (I found a weird %PRI64d format specifier on Google that seems to work.)
A: Printing large numbers may require the use of the format specifier %lld (long long int), depending on the architecture and compiler, as %ld might not be enough. In some compilers, you might need to use %i64d as the format specifier.

Raspberry Pi Pico and TKJHAT programming

Q: You have all code in github, but I do not know any GIT. What should i do?
A: Git is a fundamental tool when working in ANY project. However, it is not part of the content of the course, so you can complete all the tasks and exercises without using GIT. Just download the Github project as a zip file and extract them in a folder in your file system. Exercise 1 offers you a good step-by-step process on how to do it.
Q: Can I use my own computer for programming. I cannot attend to the campus / labs are closed when i have time ....
A:: Yes you can. You have two options: download the course VM (recommended) or installing it in your own machine.
Q: Do I need to use the provided VM
A: This is the recommended option. You can install the system in your own machine if you prefer.
Q: My Pico does not connect / i cannot upload any code
A: Check following things:
1. Please, check first that you code is compiling correctly.
2. Remember that in order to be able to upload code to the Pico, it should be in BOOTSEL mode (you must press the button.).
3. If you are using the VM be sure that you mark the device in the Devices > USB. You can save in the filter, if you do not wanna do that everytime you connect the device (check Session 1). Remember that the device can be seen by the computer in 3 different ways: Raspberry Pi RP2 Boot if the device is in boot mode; Raspberry Pi Pico (in normal execution mode) or University of Oulu TKJHAT if you are using the provided usb-debug library.
Q: Something strange is happening, but I can't figure out where in the code it's coming from...
A: There are at least three ways to troubleshoot this:
1. Use debug print statements (like printf) to trace how the program execution progresses.
2. Use the blinking led to trace how the program execution progresses.
3. You can always ask the teaching assistant in the chat or during the exercises.
A good solution for troubleshooting code issues independently is to use both debug prints and the LED simultaneously!
Q: Why does the Pico freezes immediately after startup or during execution?
A: There could be several reasons:
1. You forgot to create the tasks or call vTaskScheduler();
2. The device runs out of memory. There are a couple of things you should check here.
3. An interruption handler (ISR) that takes too long to execute can cause the device to hang, as the rest of the functionality (including RTOS) cannot proceed. Move the functionality out of the handler to the task code and control execution using a state machine. Often (always), the best practice for a handler is to simply set a state change and respond to it in the tasks.
4. A forgotten vTaskDelay() causes a task to run indefinitely, or there is an unnecessary long-running process in a task with lower priority.
5. The Pico tries to access two or more different sensors / actuators connected to the I2C in different tasks. This can be done, but you should use properly the states, to ensure that they are not accessed simultanously.
Q: Why are only one of the tasks being executed?
A: Most likely, the task that is being executed doesn’t have a vTaskDelay(), which prevents other tasks from getting execution time.
Q: The code is not doing what i expected, it is doing something totally different
A: Check that you are compiling and sending the right target to the device
Q: How can i know which the target that i need to use
A: If you are using the src/main.c in the root folder, the name of the target is given in the CMakeLists.txt located in the root folder (check variable MAIN_TARGET). If you are using any of the examples, open the CMakeLists.txt in the examples folder and check the variable DEFAULT_TARGET.
Q: Are you going to provide some kind of template for the final project?
A: Yes, actually it is the same project as the one used in the exercises, that you can download from github. You can rename template.c by main.c. If you do not do any additional changes in the CMakeLists.txt the name of the target is hat_app.

Sensors

Q: I don’t know where to start with using sensors!
A: The use of the sensors are described in the lecture material. In addition the peripherals section includes all the information that you need to run the sensors, including the functions in the SDK. We also offer some examples in the project github. Check for instance how to use the imu or how to use the display.
Check also the TKJHAT SDK for further information on which functions to use each sensor.
Finally, you have the whole code of the SDK in github. you can always have it a look.
Q: I’m trying to add sensors to my program, but the compiler can’t find their library functions..
A: For sensors and other peripherals, you need to include the TKJHAT sdk library (included in the course github project). To do that be sure that:
  1. The CMakeLists.txt of your target includes the TKJHAT_SDK
target_link_libraries(${MAIN_TARGET}
        pico_stdlib
        FreeRTOS-Kernel
        FreeRTOS-Kernel-Heap4
        TKJHAT_SDK)
  1. The C file includes the library #include "tkjhat/sdk.h"
Q: Sensor initialization (in init_x function) fails!
A: There could be many reasons, but most often it’s because you are trying to initialize multiple sensors at the same time (in different FreeRTOS tasks). You can initialize either in the main, one sensor after another, or using different states for initializing each sensor.
In future this will be solved in the SDK.
Remember also to init the TKJHAT init_had_sdk this will initialize the I2C bus so do not initialize again, that is DO NOT USE FOLLOWING CODE:
    i2c_init(i2c_default, 400*1000);
    gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
    gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
    gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
    gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);

Q: How can I visualize sensor data?
A: In the lab Session 1 we explained how to use the Arduino serial plotter to represent data.
In the lecture material, the project chapter gives tips for visualizing sensor data by printing data in the terminal using printf. You can use programs like M$ Excel, gnuplot, Python libraries, Matlab, etc.
It’s recommended to collect the sensor data in csv format, which most programs can read directly.

Graphics and Sound

Q: How do I get sound from the device?
A:TKJHAT has a simple buzzer component that produces beeping sounds. This is controlled by the SDK functions: init_buzzer, buzzer_play_tone and buzzer_turn_off. An example code file can be found in the Github project’ example.
The buzzer is connected to I/O pins not to I2C
There are plenty of examples online for playing songs with an embedded systems "ghettoblaster".
Q: How can I draw images on the screen using the LCD Screens?
A: An image is represented in bitmap format with ones and zeros, where one means the corresponding pixel is on. Our SDK is a wrapper for the Pico SSD1306 library you can directly the Pico SSD1306 function ssd1306_bmp_show_image. You can find more instructions in the official library documentation.. Your image should be converted in a adequate format (bmp) and then converted to hexadecimal in a .h file using some bin2c-like application.
You can draw images manually, pixel by pixel, using something like Paint, and then convert the image to hexadecimal by calculating it roughly yourself, or using some of the existing tools. There are also bitmap image editors available online...

State Machine

Q: How can I track the state machine’s behavior in multiple tasks?
A: By using debug print statements... so log the state changes of the state machine to the console window.

Development Environment and Console

Q: What is a debugger?
A: In embedded systems, a debugger is usually a separate physical device and associated software that allows you to control the behavior of the microcontroller and the execution of the program on it. A debugger is a very handy tool in embedded software development and is included with all modern devices and their development environments. The SensorTag debugger is the separate circuit board between the display and the device, where the green LED is always on.
Using the debugger involves setting up breakpoints in the code. You can have multiple breakpoints in the program at the same time. A breakpoint marks positions in the code (e.g., a circle or some symbol at the line of code in the editor) where you want the program execution to stop “live.” When the program stops, the debugger has access to the state of the device, memory, (sometimes even peripherals), and so on.
In the debugger software’s panel, there are various functions for program execution, such as running the program one line at a time (e.g., ‘‘step over’’) or running the program until the next breakpoint (‘‘run’’).
We are not using currently a debugger. Print debug statements or use the LED instead.

2025 Project

Q: Is it necessary to use the buttons in any of the tiers?
A: No it is not, although we belive might make simplify the worflow of your application.
Q: In the video instructions tells that we should discuss about the interruptions we have used. What if we have not used any interruptions? Is it OK not using interruptions
A: You do not need to use interruptions. However, consider if some part of your code is using hardware/software interruption (even the SDK). If no interruptions are used, tell in the video explicitly that you are not using any interruptions.

Conclusion

The person who asks questions does not get lost.
This course only gives a very faint glimpse of C and its usage. Just enough to learn how to use it as a tool for programming embedded systems.
?