writefreely.ch

Reader

Read the latest posts from writefreely.ch.

from Léonard Urban

Now that I am back from vacation, I managed to get a few things done ! Here is a list of the key areas I managed to make progres in: 1. Project managment, to have a better overview of what was done and what I need to achieve; 2. A smarter packaging system to manage multiple sensors at once; 3. Reducing memory usage by implementing static FlatBuffers using a custom emitter.

1. Project Managment

First, I finally took the time to look into project managment software, and stumbled on Kaneo, a rather minimal kanaban application that also includes a backlog and a Gantt chart. I wanted something that was easy to self-host (there is a Dokploy template for it) and a small enough featureset I wouldn't waste time learning how to use it. Now, if you want to follow the project's development, you can take a look at my kanban board !

Visually writing down what has to be done and has already been done helps me to prioritize certain features over others, and helps me stay motivated by seing the steady progress, so I am glad I finally took the time to configure everything.

2. Smarter packaging

Before, every single sensor provided its own _pack() function. This function was used to take as all the data that the sensor had accumulated since the last _pack() call and add it to the common Flatbuffer. Then, a central telemetry task would call the _pack() functions sequentially and then finally send out the final, serialized packet.

While this worked for testing purposes, it came with several issues: + It required to write extremely similar code each time I added a new sensor; + There was no check wether the packaged data exceeded the remaining available space; + Starvation was guaranteed since the sensors would alwas package in the same order.

The first issue was kind of fixed by using a large macro that could automatically generate the _pack() function for you, but the two other issues remained. To fix them, I decided to throw away this implementation to switch to a sensor-agnostic implementation with a priority system.

Generalizing the packaging

In FlatBuffer (specifically flatcc), you would typically use specialized functions for each datatype defined in your .fbs schema. To be able to handle any sensor, we use the underlying flatcc_ functions. These typically abstract away the datatype to an id, alignment and size variables. This enables us to register a sensor to the telemetry system by providing only three values, instead of providing a whole function, simplifying the work of the user.

Now we have a generic_pack() function to use instead of the ~10 individual pack functions. Since this generic function is provided by the telemetry task and not the sensor task, it has also much more context allowing for more granular control of how the data gets packaged.

Data from the sensors is appended using this (simplified workflow):

flatcc_builder_start_vector(B, size, alignment, max_count); // prepare to build scrap vector in heap
flatcc_builder_append_vector(B, byte_buf + (start_idx * size), count); // copy section of sensor data to the scrap vector
flatcc_builder_ref_t vec_ref = flatcc_builder_end_vector(B); // get offset of built scrap vector
flatcc_builder_ref_t* table_slot_ref = flatcc_builder_table_add_offset(B, id); // get offset of the sensor's final vector
*table_slot_ref = vec_ref; // map the scrap vector to the sensor's final vector
// repeat the above steps for each sensor, each with its own size, alignment and id
FripuckProtocol_Sensors_SensorBatch_end_as_root(B); // finaly commit the full FB

Currently those three values have to be digged up in the generated flatcc files, which is not ideal. In theory, these values can be calculated or referenced in the generated code, which would be ideal in the long run.

Priority System

To reduce starvation, and make sure time sensitive data gets priority, a priority system was made. A priority and age is assigned to each sensor when registering them, to determine the order in which the sensors get packaged, and thus which one can package the most data. That process is rather simple, simply adding age_step to the age of the sensor at each iteration to track how much time has passed since last data was sent, and then adding the age to the priority for the final priority. The sensor which gets the highest priority gets picked next.

This system prevents starvation but isn't optimal. Ideally, taking into account how much data the sensor has collected or what would optimally fill the FB packet would also be interesting metrics to determine the priority, but this simple system currently is sufficient for my needs.

Puting it all together

With these two new systems as well as a limit tracker, we can now create a simple packaging loop to package and send our data:

void pack_loop(flatcc_builder_t* builder, uint32_t budget) {
    for (; budget > 0;) {
        // Priority check
        struct sensor_info* s = update_age_and_pick_sensor();
        if (s == NULL) continue;

        // Managing the remaining space and packaging the sensor data.
        uint32_t bytes_written = 0;
        generic_pack(builder, &s->fb_data, budget, &bytes_written);
        budget -= bytes_written;
    ...

Adding to that a simple timeout that will not block the pack_loop when only few or slow sensors are running, and we have a much better system than before ! However, this doesn't solve our initial problem of high memory use, which requires the next adaptation:

3. Static FlatBuffers

First, we need to understand how FlatBuffers works. Here is what it is according to the docs:

FlatBuffers is an efficient cross platform serialization library [...].

To achieve this serialization, flatcc (the C implementation of FlatBuffers) first creates the individual objects and vectors that go into the final FB object, and in a second step, it compacts down those individual blocks into a single, continuous memory block that is ready to be sent. A unique twist on the serialization is that instead of growing the sequential block in only one direction, it starts in the center of the available space (offset 0), and grows data to the left (negative offset) and metadata (the position and type of the data) to the right (positive) offset.

                  ┌───────┬────────┐
                  │   FB buffer    │ Emitter ctx
                  └───────┼────────┘
                    Data  │ Vtable (metadata)
 - negative offset ◄───── │ ─────► + positive offset
                          │
                       offset 0

One major issue when using the default flatcc configuration, is that it builds this serialized block in the heap, meaning we need to allocate a huge chunk of data on the heap when the serialization starts. Since we only have so much heap space to begin with, this is a no go.

Luckily for us, the flatcc developers go us coverd and provide a custom initialization command which enables us to provode our own emitter (the object responsible for building the serialized block). This way, we can assign a static buffer to it, which prevents fragmentation and doesn't reaquire a bunch of free heap space. It is also possible to define a custom allocator, which is used when creating the temporary vectors and objects before serializing them, but this is overkill for our needs.

The custom emitter is divided into three parts: – The emitter context (ctx), which holds all the data the emitter function needs to build the serialized buffer; – The emitter function (custom_builder_emit_fun), which is called each time an object or vector needs to be added to the final buffer, and appends the data and the metadata to the respective ends of the buffer; – And finally the buffer itself, where the data will be added.

We define the buffer as simply a static array of bytes, with a “center”. Typically the center (or offset 0) won't be perfectly in the center of the static buffer, since flatcc generally produces much more data (left side) than metadata/Vtable (right side)

#define STATIC_FB_BUFFER_SIZE (2 * 1024)                       // 2KB static payload buffer
#define FB_BUFFER_OFFSET_ZERO (STATIC_FB_BUFFER_SIZE * 3 / 4)  // Index of offset 0
static uint8_t fb_buffer[STATIC_FB_BUFFER_SIZE] = {0};

Then, we need to define the context which will be passed through different function calls. To be able to build the buffer and correctly determine its size, we need to store a reference to the buffer, its capacity, the offset of the center, the min and max offsets.

typedef struct {
    uint8_t* buf;
    size_t capacity;
    flatbuffers_soffset_t zero_offset;  // Center (offset +0) of the buffer
    flatbuffers_soffset_t min_offset;   // Tracks the lowest negative offset emitted
    flatbuffers_soffset_t max_offset;   // Tracks the highest positive offset emitted
} static_emitter_context_t;

Then begins the hard part, the emitter function. It has to strictly follow the following function definition:

int custom_builder_emit_fun(void* emit_context, 
                            const flatcc_iovec_t* iov, 
                            int iov_count, 
                            flatbuffers_soffset_t offset, 
                            size_t len);

Let's go through the different arguments: – emit_context is a pointer to the context we defined earlier. – iov is an array containing data+size pairs of information we need to copy to the buffer. – iov_count is the number of elements in that array. – offset is the offset (positive or negative) where we need to write the data to. – len is the combined length of all the iov entries.

Then, the workflow is pretty simple. 1. We loop through the iov entries, 2. We calculate the final address in the buffer where the data needs to be copied to, 3. Update the offset before writing the next entry.

In code, this translates to the following (omitting bound checks and details):

for (int i = 0; i < iov_count; ++i) {
    size_t elem_len = iov[i].iov_len;
    if (elem_len == 0) continue;

    // Calculate the final address to write to 
    uint8_t* dest = &ctx->buf[ctx->zero_offset + offset];

    // copy 
    memcpy(dest, iov[i].iov_base, elem_len);
    
    // update the entry
    offset += (flatbuffers_soffset_t)elem_len;
}

Then, simply pointing to the lowest negative offset gives you a valid FB, no additional steps !

Wrappingn it up


Now that I’m back from vacation, I’ve managed to make progress on several key areas: 1. Project management, to get a clearer overview of what’s done and what’s left to achieve; 2. A smarter packaging system to handle multiple sensors more efficiently; 3. Reducing memory usage by implementing static FlatBuffers with a custom emitter.

1. Project Management

First, I finally took the time to explore project management tools and came across Kaneo, a minimal Kanban application that also includes a backlog and a Gantt chart. I wanted something easy to self-host (there’s a Dokploy template for it) with a small enough feature set that I wouldn’t waste time learning how to use it.

If you want to follow the project’s progress, you can now check out my Kanban board!

Visually tracking what needs to be done and what’s already completed helps me prioritize features and stay motivated by seeing steady progress. I’m glad I finally set this up.

2. Smarter Packaging

Previously, each sensor had its own _pack() function. This function would take all the data the sensor had accumulated since the last _pack() call and add it to a shared FlatBuffer (FB). A central telemetry task would then call these _pack() functions sequentially and send out the final serialized packet.

While this worked for testing, it had several issues: – It required writing nearly identical code for each new sensor. – There was no check to ensure the packaged data didn’t exceed the available space. – Starvation was inevitable since sensors were always processed in the same order.

The first issue was partially fixed using a macro to auto-generate the _pack() function, but the other two remained. To address them, I decided to scrap this approach and switch to a sensor-agnostic implementation with a priority system.

Generalizing the Packaging

When using FlatBuffers, you typically use specialized functions for each datatype defined in your .fbs schema. To handle any sensor, we use the underlying flatcc_ functions, which abstract the datatype into an ID, alignment, and size. This allows us to register a sensor in the telemetry system by providing just these three values, instead of an entire function, simplifying the user’s work.

Now, we have a single generic_pack() function replacing the ~10 individual pack functions. Since this generic function is provided by the telemetry task rather than the sensor task, it has more context, enabling finer control over how data is packaged.

Sensor data is appended using this simplified workflow:

flatcc_builder_start_vector(B, size, alignment, max_count); // Prepare to build scrap vector in heap
flatcc_builder_append_vector(B, byte_buf + (start_idx * size), count); // Copy section of sensor data to the scrap vector
flatcc_builder_ref_t vec_ref = flatcc_builder_end_vector(B); // Get offset of built scrap vector
flatcc_builder_ref_t* table_slot_ref = flatcc_builder_table_add_offset(B, id); // Get offset of the sensor's final vector
*table_slot_ref = vec_ref; // Map the scrap vector to the sensor's final vector
// Repeat the above steps for each sensor, each with its own size, alignment, and ID
FripuckProtocol_Sensors_SensorBatch_end_as_root(B); // Finally commit the full FlatBuffer

Currently, these three values (ID, alignment, size) must be manually extracted from the generated flatcc files, which isn’t ideal. In theory, they could be calculated or referenced in the generated code, which would be a better long-term solution.

Priority System

To prevent starvation and ensure time-sensitive data gets priority, I implemented a priority system. Each sensor is assigned a priority and an age when registered. These determine the order in which sensors are processed and how much data they can package. The process is straightforward: at each iteration, age_step is added to the sensor’s age to track the time since its last data was sent, and then the age is added to the priority to compute the final priority. The sensor with the highest priority is selected next.

This system prevents starvation but isn’t perfect. Ideally, we’d also consider how much data a sensor has collected or how to optimally fill the FlatBuffer packet. However, this simple system currently meets my needs.

Putting It All Together

With these two new systems and a limit tracker, we can now create a simple packaging loop to package and send data:

void pack_loop(flatcc_builder_t* builder, uint32_t budget) {
    for (; budget > 0;) {
        // Priority check
        struct sensor_info* s = update_age_and_pick_sensor();
        if (s == NULL) continue;

        // Manage remaining space and package sensor data
        uint32_t bytes_written = 0;
        generic_pack(builder, &s->fb_data, budget, &bytes_written);
        budget -= bytes_written;
        ...
    }
}

Adding a simple timeout ensures the pack_loop doesn’t block when only a few or slow sensors are running. This results in a much better system than before. However, it still doesn’t address the initial problem of high memory usage, which brings us to the next adaptation:

3. Static FlatBuffers

First, let’s recap how FlatBuffers works. According to the docs:

FlatBuffers is an efficient cross-platform serialization library for C++, Java, Python, Go, and more.

Unlike traditional serialization formats (e.g., JSON or Protobuf), FlatBuffers does not serialize or deserialize data in the conventional sense. Instead, it directly constructs a binary buffer in memory, where data is organized for zero-copy access. This means you can read fields directly from the buffer without parsing or deserialization steps. To build this buffer, flatcc (the C implementation of FlatBuffers) follows a two-step process:

  1. It first creates intermediate vectors and tables (temporary structures) for each object defined in your .fbs schema.
  2. It then compacts these into a single, contiguous memory block ready for transmission. A unique aspect of FlatBuffers is its bidirectional growth mechanism. Instead of growing the buffer in one direction, it starts at the center (offset 0) and grows:
  3. Data (e.g., vectors, scalars) toward negative offsets (left).
  4. Metadata (e.g., VTables, which store field layouts for tables) toward positive offsets (right). This minimizes alignment gaps and ensures the final buffer is tightly packed.
                  ┌───────┬────────┐
                  │   FB buffer    │ Emitter ctx
                  └───────┼────────┘
                    Data  │ Vtable (metadata)
 - negative offset ◄───── │ ─────► + positive offset
                          │
                       offset 0

But why does it matter ? By default, flatcc allocates this final buffer on the heap, which is problematic for embedded systems with limited memory. Fortunately, flatcc allows us to provide a custom emitter—a callback function that redirects buffer construction to a static memory region of our choosing. This avoids dynamic allocation entirely. It’s also possible to define a custom allocator for temporary vectors and objects before serialization, but that’s overkill for our needs.

The custom emitter consists of three parts: – The emitter context (ctx), which holds all the data the emitter function needs to build the serialized buffer. – The emitter function (custom_builder_emit_fun), called each time an object or vector needs to be added to the final buffer. It appends data and metadata to their respective ends of the buffer. – The buffer itself, where the data is stored.

We define the buffer as a static byte array with a “center.” Typically, the center (offset 0) isn’t perfectly centered in the static buffer, as flatcc usually generates more data (left side) than metadata/vtable (right side):

#define STATIC_FB_BUFFER_SIZE (2 * 1024) // 2KB static payload buffer
#define FB_BUFFER_OFFSET_ZERO (STATIC_FB_BUFFER_SIZE * 3 / 4) // Index of offset 0
static uint8_t fb_buffer[STATIC_FB_BUFFER_SIZE] = {0};

Next, we define the context passed through function calls. To build the buffer and correctly determine its size, we need to store a reference to the buffer, its capacity, the center offset, and the min/max offsets:

typedef struct {
    uint8_t* buf;
    size_t capacity;
    flatbuffers_soffset_t zero_offset;  // Center (offset +0) of the buffer
    flatbuffers_soffset_t min_offset;   // Tracks the lowest negative offset emitted
    flatbuffers_soffset_t max_offset;   // Tracks the highest positive offset emitted
} static_emitter_context_t;

Now, the tricky part: the emitter function. It must strictly follow this definition:

int custom_builder_emit_fun(void* emit_context,
                            const flatcc_iovec_t* iov,
                            int iov_count,
                            flatbuffers_soffset_t offset,
                            size_t len);

Let’s break down the arguments: – emit_context: A pointer to the context we defined earlier. – iov: An array containing data+size pairs of the information to copy to the buffer. – iov_count: The number of elements in that array. – offset: The offset (positive or negative) where the data should be written. – len: The combined length of all iov entries.

The workflow is straightforward: 1. Loop through the iov entries. 2. Calculate the final address in the buffer where the data should be copied. 3. Update the offset before writing the next entry.

In code, this looks like (omitting bounds checks and minor details):

for (int i = 0; i < iov_count; ++i) {
    size_t elem_len = iov[i].iov_len;
    if (elem_len == 0) continue;

    // Calculate the final address to write to
    uint8_t* dest = &ctx->buf[ctx->zero_offset + offset];

    // Copy
    memcpy(dest, iov[i].iov_base, elem_len);

    // Update the offset
    offset += (flatbuffers_soffset_t)elem_len;
}

Once all data is written, the lowest negative offset points to the start of a valid FlatBuffer—no further processing needed!


Wrapping Up

While I haven’t been able to work on the project as much as I’d have liked, I’m glad to see it moving forward again. I’m also happy to see my memory issues disappear, hopefully for good 😅.

Over the next month, I’ll try to dedicate as much time as possible to the project. Right now, I’m focusing my efforts on getting the camera to work and laying the initial foundations for the laptop → e-puck commands. This involves coordinating the radio and controller chip, as well as the Lua VM I’ve started implementing.

C you next month!

Project Github page: https://github.com/Uhrbaan/fripuck2

 
Lire la suite...

from i6831r6dyf0q

Speed Without Compromise: A Practical Guide to Slashing Your CNC Production Cycle

In the world of precision engineering, there is a constant tug-of-war between speed and quality. When you are sourcing custom CNC parts, the pressure to reduce cnc lead time can often lead to “shortcuts” that result in scrapped parts or dimensional inaccuracies.

However, reducing lead time doesn’t have to mean compromising on tolerances. By optimizing the workflow from the initial design phase to the final inspection, manufacturers and engineers can achieve rapid cnc machining without sacrificing an ounce of precision.

Here is a practical, step-by-step guide to streamlining your CNC production cycle.

1. Optimize for Manufacturability (DfM)

The most significant delays in CNC machining often happen before the machine even starts. “Design for Manufacturing” (DfM) is the process of designing parts specifically to be easy to machine.

  • Avoid Deep Pockets: Deep, narrow slots require long tools that vibrate (chatter), forcing the machinist to slow down the feed rate.
  • Standardize Radii: Using standard tool diameters for internal corners prevents the need for custom tooling or complex multi-axis movements.
  • Simplify Tolerances: Don’t apply a ±0.001 tolerance to every dimension if only two critical holes actually require it. Over-tolerancing increases inspection time and scrap rates.

By focusing on these details during cnc prototyping, you can identify bottlenecks early and ensure the transition to full-scale production is seamless.

2. Strategic Tooling and Process Selection

Choosing the right process for the right geometry is key to speed. Many projects fail to optimize by using a single machine for a complex part when a hybrid approach would be faster.

  • The Milling vs. Turning Split: For cylindrical components, utilize specialized CNC turning services to achieve high speeds and superior surface finishes. For complex prisms or blocks, leverage high-speed CNC milling services.
  • Tooling Presets: Use tool presetters to measure tool lengths and diameters offline. This means the machine doesn't sit idle while the operator manually probes tools.
  • High-Feed Cutters: Invest in high-feed milling cutters that can remove large volumes of material quickly while maintaining a stable cut, drastically reducing roughing time.

3. Implement a “First-Article” Fast Track

Waiting for a full batch to be completed before inspecting them is a recipe for disaster. If the first part is wrong, the entire batch is scrap.

To reduce lead time, implement a First-Article Inspection (FAI) process: 1. Machine a single piece. 2. Conduct a full dimensional report. 3. Get immediate sign-off before proceeding to the rest of the lot.

This is particularly critical in high-stakes sectors like aerospace cnc machining, where material costs are high and tolerances are razor-thin. Finding an error on the first part saves days of wasted production.

4. Streamline Material Sourcing and Fixturing

The machine cannot run if it is waiting for material or if the setup takes four hours.

  • Standard Stock Sizes: Design your parts to fit standard raw material sizes. Custom-ordering specialized billets adds weeks to your cnc lead time.
  • Modular Fixturing: Use “zero-point” clamping systems. These allow a technician to swap a workpiece in seconds with micron-level repeatability, meaning the machine spends more time cutting and less time in “setup mode.”
  • Batching Similar Parts: If you have multiple custom CNC parts with similar geometries, machine them in a single setup (multi-part fixturing) to reduce the number of times the machine needs to be recalibrated.

Final Thoughts

Reducing lead time is not about pushing the machine to its breaking point; it is about removing the “waste” from the process. By combining smart DfM, strategic tool selection, and rigorous first-article checks, you can achieve the speed of rapid cnc machining while maintaining the quality standards your project demands.

Whether you are iterating a prototype or scaling a production run, the key is to optimize the workflow long before the “Cycle Start” button is pressed.

 
Read more...

from i6831r6dyf0q

Field notes from the workbench this week. I spent most of the afternoon squaring up a jig so repeat cuts land in the same place every time, which saved more effort than any single clever trick. Small tolerances add up: a fraction of a millimetre off at the start becomes a visible gap by the end. I keep a running log of what worked and what wasted time, because memory is unreliable after a long session. Cheap calipers, a sharp pencil, and patience beat expensive tools used carelessly. Next up is tidying the bench and labelling the offcuts so the next build starts faster.

 
Read more...

from Léonard Urban

Over the last two months, I was busy with my exam sessions and wasn’t able to make as much progress as I would have liked. However, I did start planning a smarter serialization approach for sensor data. Currently, all samples are packed one after another, which causes FlatBuffers to use too much RAM. The core idea is to track how much data has been packed so far and use a priority system to decide which packets get packed first. I don’t have much to show yet, though.

During that time, I also met with my professors to discuss the project, which forced me to clarify what I want to achieve with Fripuck. I identified four key improvements I could bring:

  • Data analysis
  • Networking
  • Asynchronous API
  • On-board programming

Slide from my presentation explaining why I am working on the project. It reads: There are 2 reasons why I feel the need to improve the e-puck2 robot: 1. During the robotics course, a project was rendered impossible due to low data resolution. 2. Personal interest in exploring embedded systems development, a topic not fully covered in the university curriculum. Improvements on 4 aspects: enabling easy data analysis, improved networking, asynchronous API, and enabling on-board robotics.

Data Analysis

The current API and firmware for the robot focus on real-time data, and it is up to the user to store and analyze it. My goal is to allow the firmware to save multiple data points in batches and send them at once, providing higher time resolution. The API would then store this historical data, allowing users to query it.

Improved Networking

A major annoyance when working with the robot is unstable networking. When 10 students work simultaneously on 10 different robots, the network can fail. The new API should be able to reconnect the robot as quickly as possible to avoid disrupting the user.

Planned structure for the firmware/API

Asynchronous API

This is another step toward improving time resolution. Currently, the Python API used to communicate with the robot relies on a single .go_on() call that sends instructions and waits for sampled data. This causes the program to spend most of its time waiting for a network response, making the robot feel unresponsive. My goal is to make data exchange happen in the background so it doesn’t interfere with the user’s code. I also want to decouple the sending and receiving of data.

On-board Robotics

Currently, the robot can only be controlled remotely, or the user must modify the robot’s firmware (which is not suitable for the target audience). I would like to add a small on-board interpreter, likely using Lua (since it is lightweight and easy to embed), to configure the robot and execute simple commands. This would allow users to change robot-specific features without recompiling the firmware or let students test latency when running scripts on-board or over the network.


Going Forward

This summer, I’ll have plenty of time to work on this project and, hopefully, complete 80% of it. Right now, the most urgent tasks are to configure my new OS (I distro-hopped to openSUSE) and create a roadmap of the features I need to implement. On the academic side, I need to identify measurable goals to evaluate the success of my project.

 
Read more...

from P É O N A G E

— Et alors, il y avait quoi sur ce papier ?

Le bar aux couleurs ocre et bois est encore peu fréquenté. Sur la table carrée, Agathe a étalé quelques objets sortis de son sac, un carnet, un livre, et le téléphone mis en mode vibreur pour mieux profiter du moment.

— Je sais pas, j'y suis pas allé. — Quoi, t'es même pas descendu voir, par curiosité ?

L'espace autour est devenu son terrain familier pour une heure. Je contemple le verre toujours plein en face d’elle. Elle n’en a bu qu’une toute petite gorgée, alors que le mien est déjà à moitié vide.

— Non, j'ai décidé ça à pile ou face.

Agathe reste immobile un instant. Pas un mouvement de cils. Elle doit être vraiment sérieuse, elle me demande :

— Mais tu fais vraiment tous tes choix comme ça ? — Les décisions qui demandent un effort, oui.

Elle ne touche toujours pas à son verre. Avec elle, je ne ressens aucun jugement. Pour ça que j'ose avouer ce que je ne dirai jamais à l'autre.

— Franchement, je sais que c'est facile à dire, mais tu devrais changer de psy. — Je suis obligé de la voir, c’est la psy du travail. J'ai des convocations obligatoires pour pouvoir conserver mon chômage.

Un geste de dépit, sa main plonge dans le petit bol de cacahuètes.

— Ça me dégoûte ce chantage aux allocations…

Les cacahuètes restent dans sa main comme si son écœurement était en rapport avec l'appétit. Je garde le silence, alors elle finit par se mettre à grignoter sa prise. Elle réfléchit.

— Hmm… mais alors, ça veut dire que pour venir me rejoindre tu n'as pas choisi non plus ? Pas très valorisant… C’est un lancer de pièce qui a répondu oui à mon invitation ?

Elle a changé de ton. Son petit air ironique, je vois bien qu'elle voudrait détendre l'atmosphère. Mais à elle, je ne peux pas mentir.

— Ben oui.

Ses yeux partent en coin vers la grande vitre du bar par laquelle on voit passer vélos et trottinettes. Elle continue de mâchonner les billes jaunes qu'elle s'enfile une par une. J'aimerais lui montrer que j’apprécie son attention. Je dis quelque chose, très maladroit, un truc facile, pour remplir le silence.

— Tu sais, ma psy c'est toi.

Là ses sourcils se soulèvent. Elle agrippe le contenant qu’elle s’apprête à vider du peu de bière restant, avant de me dire, sans mentir elle non plus :

— Mouais. Tu sais que c'est une charge mentale ça pour les femmes, de servir de confidente aux mecs ?

Je baisse les yeux pour afficher une prise de conscience. Elle ne rigole qu'à moitié.

— Je vais quand même te donner un vrai avis. Et tu es obligé de l'écouter jusqu'au bout, tu l'as bien cherché.

Sans m’en rendre compte j’ai descendu ma conso pendant qu’on se parlait. Ça y est, maintenant mon verre est vide, et je n’ai rien de très intelligent à répondre :

— Ça va me coûter combien ? — Zéro, justement c'est ça le problème du travail féminin gratuit. Mais je vais quand même te dire… peut-être qu'il faut que tu l'entendes de la bouche de quelqu'un…

Agathe vide d'un trait le fond de bulles dans sa chopine, avant de la laisser retomber lourdement sur la table.

— … Je pense, enfin je crois, que la menace de la guerre, ça nous atteint plus ou moins. Même quand on ne le montre pas. Comme toi, tu vois tu ne m'en parles jamais, mais peut-être que tu devrais te poser sérieusement la question.

Je reste muet. Par respect pour cet effort envers moi. Et parce que la moindre évocation du sujet me fait mal au ventre.

— … Tu devrais te demander s'il n'y a pas un rapport.

Un réflexe m'échappe en entendant ça, j'inspire fort par le nez, je m'en veux tout de suite. Je n'avais ni l'intention de montrer de l'agacement ni de laisser transparaître à quel point la question pouvait me toucher. Mais ça ne l'empêche pas de continuer :

— Tu crois pas que t'en remettre au hasard, au lieu de faire tes propres choix, ça a un rapport avec la menace qui nous plane dessus ?

Je continue à me taire. Tous mes efforts, je fais tout ce que je peux, pour ne pas lui envoyer d’autres signaux désagréables. Une amie comme ça on n'en trouve pas sous chaque dessous-de-verre.

— … Je suis pas psy, d'accord, mais ton lancer à pile ou face, c'est pas sain, c’est pas bon pour toi. Moi je crois qu’il y a un lien inconscient.

Je sais pas si c'est mon comportement, mais Agathe a soudain retrouvé une voix de fille trop gentille, la voix qu'elle a quand elle est émue :

— … Un lien avec cette horreur de tirage au sort pour nous envoyer à la guerre.

[CC BY]

 
Lire la suite...

from Léonard Urban

This month I've been quite busy with University work and had less time to focus on Fripuck. Still, I've managed to add new sensors and solve some pesky errors !

New sensors

The e-puck2 robot is equipped with a ring of 8 proximity sensors (IR reflectors). I followed the architecture of the previous implementation. It cleverly turns the IR ligths of the sensors on and off at specific time intervals to limit interference and measure the ambient light levels.

This is a significant step-up of my previous implementation, which kept the IR lights always on and scanned the sensors continuously. Not only did this produce interference in the results, but also increased power consumption.

This month also brought three sensors living on the I²C connection: the Time-of-Flight (ToF), the Inertial Measurement Unit (IMU) and the ground sensors.

I²C stability issues

I²C is a communication protocol where a master can communicate to multiple slave on the same wire. On the e-puck2, three sensors are configured and transfer their data over I²C: the ToF, IMU and ground sensors.

At first, the I²C connection seemed to work for the ToF, but wouldn't for the other sensors, always returning HAL_BUSY error. Looking online, I found that I²C can be quite unstable on some STM chips, especially when using the standard HAL_I2C_Mem_Read/Write functions. I decided to copy the implementation of the vl53l0x ToF api code, which used the HAL_I2C_Master_Receive/Transmit functions directly.

Here is how my custom 2c_read/write_reg was implemented, if it can be of use for anyone:

HAL_StatusTypeDef i2c_read_reg(uint8_t dev_addr, uint8_t reg, uint8_t *buffer, uint16_t len)
{
    HAL_StatusTypeDef res;
    osMutexAcquire(i2c_mutex, osWaitForever);

    // Announce which device/register will be sent to
    res = HAL_I2C_Master_Transmit(i2c_handle, (dev_addr << 1), &reg, 1, 100);

    if (res == HAL_OK)
    {
        // Recieve data from the slave
        res = HAL_I2C_Master_Receive(i2c_handle, (dev_addr << 1), buffer, len, 100);
    }

    osMutexRelease(i2c_mutex);
    return res;
}

HAL_StatusTypeDef i2c_write_reg(uint8_t dev_addr, uint8_t reg, uint8_t *buffer, uint16_t len)
{
    // Local buffer to combine reg + data
    uint8_t tmp[len + 1];
    tmp[0] = reg;
    memcpy(&tmp[1], buffer, len);

    osMutexAcquire(i2c_mutex, osWaitForever);
    HAL_StatusTypeDef res = HAL_I2C_Master_Transmit(i2c_handle, (dev_addr << 1), tmp, len + 1, 100);
    osMutexRelease(i2c_mutex);

    return res;
}

Python API

The python API now internally exposes an Abstract Base Class that makes it very easy to implement the reception of new sensor data. This framework has been used to implement all the sensor management in the python API, significantly reducing code duplication.

What's next ?

Next month, I'll be working more on my upcoming exams, so it will probably be a quite uneventful month.

In the available time I have, I will try to come op with a good priority system to manage which sensor data gets packaged when and sent. Currently, if I let too many sensors run at once, the Flatbuffers packet will consume so much ram that the program crashes. My objective is to smartly cut up the incoming data streams to control the final size of my Flatbuffers packet and make sure no streams are getting starved.

Wrapping up

While this month didn't bring as many features as I would have hoped, I am still happy with what I achieved considering the limited amount of free time at my disposal. I am also pleased to see the I²C issue fixed, which has been bothering me for some time now.

 
Lire la suite...

from Léonard Urban

Hi there 👋 I'm Uhrbaan, and for my bachelor thesis, I am working on updating the e-puck2's codebase and API to better fit the needs of my university.

This blog serves as a monthly update on the progress I make on that project over the next year.

What is the e-puck ?

The robot was designed by the EPFL, who describe them the following:

The e-puck is an educational robot that helps generations of students learn about embedded systems and robotics. First developed at EPFL in 2004 by Francesco Mondada and Michael Bonani, a new version was released in 2018, produced by GCtronic in Ticino. [source]

Essentially, they are small robots equipped with many small sensors to help students make their first steps into mobile robotics.

The e-puck2 robot and its many sensors

The e-pucks used at my university are built and maintained by GCtronic, a small Ticinese company. They are also the authors of the main code running on these robots and also produced a C API to talk to the robots over the network. This API was later replaced by a Python API made by a university student during their bachelor thesis (just like me), which later also introduced computer vision capabilities through YOLO.

What is Fripuck ?

Fripuck is my addition to this educational tool (if it works out 😅) ! The idea to work on the e-puck2 as my bachelor thesis rose out of two frustrations I encountered while working with the robots: (1) the blocking nature of the API and (2) the focus on real-time robotics, limiting the ability for data analysis/signal processing.

Good software is born of frustration

— Someone, probably

A second reason I started this project, and why I am not only modifying/rewriting the API but also the firmware, is that I got really interested in embedded development. The university sadly doesn't have courses about embedded programming, so I figured the best I could do was learn that subject on my own, and with my limited time, doing it during my bachelor thesis seemed to be the best option.

Fripuck itself is the combination of three pieces of software: the firmware of the STM32F4 chip that controls the robot and all the sensors, the firmware of the ESP32 responsible for the communication over Wi-Fi with the student's computer, and finally the API (Python or Go for testing). The name of the project is a combination of e-puck and Fribourg, the university with which I am doing my thesis.

What do I want to achieve? I technically already started the project last semester, so about 4 months ago, just as an “exploratory” phase. This helped me to read a bit through the existing code base, get familiar with the hardware, and explore the limitations of the chip. For example, I got a Lua VM working on one of the two chips and controlling the LEDs with it.

For the moment, I am mostly working on re-implementing the firmware and the API to reach feature parity (mostly, some features I do not care about since the university doesn't use them) with the old software, the status quo, while still keeping some nice improvements, like the API being multi-threaded and asynchronous by default, and the firmware using a more modern build system/development environment (PlatformIO), moving away from a custom serialization protocol to use Flatbuffers and using a real-time operating system more common in the academic world (FreeRTOS over ChibiOS).

The progress can be tracked on GitHub at https://github.com/Uhrbaan/fripuck2 (at the time of writing, the table is mostly empty and the README.md isn't even fully finished yet).

Ideally, if I have the time, I would like to add new features as well, like a full audio stream from the robot to the clients, which would enable voice commands; a Lua VM to make the robots work offline; or even audio playback, which could make the robots talk, maybe transforming them into AI assistants, who knows! 🤷 Another big goal would be to increase the video playback speed, but I doubt it is possible to achieve more than 10 or 15 frames per second.

What have I achieved so far?

Right now, most of the foundations have been laid out. I have a rather precise vision of the architecture of the whole system; the firmware is working, the Python API is working, and the robot can send and receive packets serialized as FlatBuffers. The only important foundational work that is remaining is managing the commands coming from the client.

Once that is working, there will be a lot of work to re-add all the sensors, although I will probably be able to use a lot of the existing code to achieve this.

What are you working on right now?

Currently, I am testing the telemetry process (the robot reads a sensor, packages it, sends it over the network, and the client receives it) by implementing the simple time-of-flight sensor and sending that data over the network. Once that is working, I will proceed to work on the commands.

Wrapping up

So far, I've been really enjoying the process. C was the first language I ever learned, and I hope this project is going to elevate my C skills to the next level. I am also having fun discovering the world of embedded programming, although I don't find it as welcoming as other domains, since documentation and tutorials aren't as readily available. I often find myself having to read through multiple example projects to understand what I am supposed to do, but on the bright side, code reading and comprehension is equally as important of a skill to train as writing it (since AIs are going to take that away apparently 🤷).

Next month, I'll probably go a bit more into the architecture I've planned and some technical challenges I've come across. Anyway, if you stayed through the whole text, thank you for your time !

 
Lire la suite...

from Café histoire

Dans son ouvrage How I Take Photographs, Daido Moriyama présente quelques-unes de ses démarches. Une des premières présentée consiste pour lui à parcourir dans les deux sens une rue fréquentée. Pour lui, > «There is no better place to start than an ordinary shopping street – the kind you find in front of railway stations in any town or city in Japan.*»

Pas de rue commerçante ordinaire, puisque c'est dimanche, mais le bord de quai à Montreux, du côté de Territet, que nous avons parcouru dans les deux sens pour cette flânerie photographique inspirée par Daido Moriyama. Sans prétention.

Premier passage

La descente vers le bord du lac.

Le départ du quai près de l'Auberge de jeunesse de Montreux

Le port de Territet

Le Contre Temps, hors-saison et dans l'attente de la saison estivale

Le pêcheur

L'appel du large ou la joie espérée du pêcheur

Que serait Montreux sans ses palmiers et la promesse d'un doux séjour?

Sur le chemin du retour ou le re-passage

Piscator lacustrus. Labubu des Espaces

Le texte suivant accompagnait cette réalisation de la commune de Montreux: > Personnages issus de l’univers fantastique de l’artiste Kasing Lung. L’expression de cette peluche est souvent décrite comme espiègle, malicieuse, ou même légèrement sauvage, ce qui lui donne une personnalité forte et attachante. Ces figurines se déclinent sous divers coloris et formes tout en possédant leur propre nom. Ces sculptures végétales ont été imaginées et réalisées par les jardinier.ère.s de la Commune de Montreux.

« Pour une cause pure avec une épée pure »

Si je suis passé de nombreuses fois sur ce quai, c'est la première fois que je suis attardé sur ce monument et que j'y ai prêté attention. Probablement que le côté hors-saison de cette promenade dominicale a mis plus particulièrement en évidence le monument. Le texte sur la face présentée de cet obélisque est le suivant :

A LA GLOIRE DE LA FINLANDE ET DE SON PEUPLE HÉROÏQUE A LA MÉMOIRE DU NOBLE CHEVALIER LE BARON CARL GUSTAF MANNERHEIM MARECHAL DE FINLANDE 1867–1951 CANDIDA PRO CAUSA ENSE CANDENDO

En recherchant sur internet à l'aide du texte du document, il est possible d'arriver sur une page de l'armée suisse présentant le monument. On y apprend que le monument a été réalisé en 1955. Le baron Carl Gustaf Mannerheim (1867 – 1951), maréchal de Finlande, est devenu le premier commandant en chef de la jeune armée finlandaise créée lors de l’accession du pays à l’indépendance après la Révolution russe de 1917. Le Dictionnaire historique de la Suisse nous apprend que, durant la “guerre d'hiver” (1939-1940), il organisa la résistance de son pays en 1940-1941 contre les unités soviétiques et devint ainsi le symbole de l'indépendance nationale. Sous son influence, la Finlande se rapprocha de l'Allemagne dès le milieu de l'année 1940 et entra en guerre à ses côtés contre l'Union soviétique (“guerre de continuation”, 1941-1944). Enfin, il devint président de la République jusqu’en 1946. À partir de 1943, il vint régulièrement faire des séjours de santé à Lugano, Lausanne et Montreux (sanatorium de Valmont où il rédigea ses mémoires). L'article de Wikipedia le concernant me permet de comprendre que la citation Pro causa candida Ense candido (« Pour une cause pure avec une épée pure ») figurant sur le monument de Territet est la devise des Mannerheim. En effet, Wikipedia m'indique que cette citation figure également sur son tombeau du cimetière militaire de Hietaniemi à [Helsinki].(https://fr.wikipedia.org/wiki/Helsinki).

Voilà pour le côté week-end studieux de cette flânerie. Sur place, nous arrivons presque au terme de ce parcours.

Un dernier coup d’œil sur les quais.

Avant d'entreprendre la remontée…

J'espère que cette promenade vous aura plu et vous incitera tant à utiliser votre appareil photo dans vos pérégrinations qu'à entreprendre ce type de ballade.

Tags : #aucafé #Histoire #Roadbook #suisse🇨🇭 #montreux #photographie #twice #sonya6000 #sigma1850f28

 
Lire la suite...

from P É O N A G E

La porte est restée ouverte un moment. Je n'ai pas compris pourquoi tout de suite. Jusqu'à ce que les grosses roues d'un fauteuil électrique franchissent le seuil. La personne installée dedans a glissé sous la lumière et les roues se sont immobilisées. Elle pilote d'un doigt sur un petit joystick. Elle est de dos. Une femme maquillée, avec un pantalon noir et un manteau très classe, des escarpins, et un chapeau qui lui fait comme un gâteau sur la tête. Je n'avais jamais vu quelqu'un porter un chapeau entortillé comme ça avec des rubans et de la mousseline, sauf dans des fêtes déguisées. Un mec la suit. Il est raide lui, dans son costume noir avec une cravate grise. Il est allé faire un signe à la conductrice, mais au lieu de sortir elle a déclenché l'ouverture du coffre de la Porsche, qui monte lentement. Et la femme en fauteuil, derrière, attend en regardant le mouvement ascendant du haillon, avec le mec en blazer qui est revenu à côté d'elle se poster comme un piquet, regard droit, les mains l'une sur l'autre devant les cuisses. Le vent souffle, on voit danser les ombres d'arbres projetées par un lampadaire. Et ce chapeau de grande bourgeoise, il me fascine. Tellement ridicule, mais imposant à la fois. On ne peut pas l'éviter du regard. Il y a deux autres en costume noir qui arrivent. Un homme avec une femme assez jeune, qui transportent à bout de bras une longue planche en bois toute ficelée. Les costumes noirs c'est pour les domestiques. Je le sais parce que mon frère a bossé dans un hôtel de luxe. Devant le coffre ouvert, les deux employé⋅es s'arrêtent. On dirait qu'illes attendent des instructions. La femme en fauteuil fait des tout petits mouvements du menton. Son cou ne peut pas bouger, mais ses lèvres articulent des phrases. Les autres l'écoutent apparemment : après son intervention, le gars et la jeune déposent très doucement le colis tout plat à l'entrée du coffre, et illes se mettent à le faire coulisser dedans avec précaution. J'avais tort au sujet des bourges je crois, c'est un couvre-chef qui fait la différence.

Sauf qu'il y a un problème. Ça ne rentre pas jusqu'au fond. Le fauteuil se déplace maintenant. La dame au chapeau fait le tour du coffre pour venir inspecter. Les manutentionnaires ressortent une partie de ce chargement pas très épais mais qui doit être cher précieux. Illes le font coulisser encore un coup pour que ça rentre en diagonale cette fois. Le résultat n'a pas l'air satisfaisant non plus, alors le fauteuil se remet à tournoyer. Elle fait des demi cercles méticuleux en roulant, puis se fige et pivote pour se tourner parfaitement en face du coffre. C'est sûrement un tableau de valeur dans l'emballage. Ou un grand tirage photographique, un truc de collectionneuse d'Art. La portière s'ouvre enfin à l'avant. La situation doit être désespérée pour la forcer à sortir. La conductrice met les pieds dehors sans se presser. Des cheveux châtains courts, lunettes de soleil passe-partout. Elle ouvre une portière à l'arrière, tout aussi calmement, et se penche à l'intérieur du véhicule. Elle n'a pas adressé un regard aux autres. Je les regarde s'agiter quand le bout de planche qui dépassait disparaît entièrement. Tout le monde veut inspecter le résultat. La conductrice se redresse, avant de refermer la portière. Elle fait quelques pas, toujours sans précipitation, en direction du groupe qui contemple le cul du SUV. Avec la femme au chapeau enflé, elle échange un ou deux mots, pendant qu'une bourrasque chahute cette coiffe qui couronne le fauteuil électrique. La fermeture du haillon de coffre se déclenche à distance, et le chapeau ne s'est pas envolé, il est sûrement très bien attaché. La chauffeuse, une main dans la poche, surveille patiemment le mouvement de fermeture. Tout le monde observe le coffre attentivement. Quand il n'y a plus rien à voir, elle retourne sans précipitation s'asseoir au volant. Le vent se remet à souffler. Comme dans mes craintes, tout se précipite. La voiture commence à rouler, vers la barrière du parking. La dame en fauteuil se retourne vers la porte arrière du casino. Deux des employé⋅es sont déjà rentré⋅es. La barrière se soulève, la Porsche franchit cette démarcation. Elle va s'éloigner silencieusement. Je recentre ma visée sur la backdoor. Les pneus cannelés du fauteuil qui s'approchent de la lourde issue de secours. Un coup de vent secoue les grandes ombres autour. Le fauteuil s'est engagé, il disparaît derrière l'acier du battant de porte. Quelques secondes suspendues, avant que cette ouverture ne se replie définitivement.

Mes jumelles braquées sur le carré de lumière déserté, je contemple l'absence soudaine. Elle laisse un goût que je ne sais pas expliquer. Les histoires ont un début, un milieu, et un néant. Je n'arrive pas à me décrocher de cette scène remplie brusquement par le néant, sous l'éclairage automatique qui va bientôt s'éteindre. Illes ont disparu.

Tous les récits qui étincellent. Et jamais de conséquences.

Le vide ne règne pas totalement. Une feuille de papier vole. Happée dans la lumière. Elle décrit une jolie courbe en montant à la verticale, avant de flotter un instant et de redescendre devant ce mur crépi où on s'agitait il y a une minute.

Un simple bout de papier qui pourrait raconter tellement. Est-ce qu'elle leur appartenait, perdue par maladresse dans les déplacements autour du véhicule ? Un bon de commande, un reçu de gains, une note d'instructions, ou même une bête liste de courses...

Un nouveau coup de vent tire la feuille volante dans la direction opposée. À Quelques mètres, dans les buissons qui bordent l'aberration écologique, elle est allée terminer ses volutes.

Je reste les yeux fixés sur cette forme accidentelle prise dans les branchages. Le cœur qui bat à nouveau. L'excitation dépasse même le malheur d'avoir froid et de se sentir seul. Je ne pense qu'à une chose. Descendre là-bas pour récupérer cette feuille de papier. Un petit risque à prendre, comme une nouvelle mise.

C'est la pièce qui va décider. Précipite les conséquences.

Pile, ou face.

[CC BY]

 
Read more...

from P É O N A G E

Le vent qui souffle avant minuit vient de se lever. Dans la vallée on dit que ça annonce un temps nuageux. J'enfouis mon menton dans le cache-cou de cycliste, devant le ciel étoilé, et je repense à la boucle qu'il faudra réintégrer une fois mon cul décollé de ce banc. Un sample de réalité qui tourne entre quatre murs. Le hasard décidera de l'heure de mon retour, mais quelque soit le prochain résultat du lancer de la pièce de monnaie, je sais que je reviendrai toujours dans un salon carrelé blanc. Encore une vérité qui laisserait la psy sans voix : les propriétaires dallent leurs appartements tristes comme des labos pour nettoyer plus facilement les traces de nos existences. C'est pas juste du mauvais goût en décoration. C'est intentionnel.

Avant de rentrer dans mon petit studio vide, je veux la suite du spectacle. Il y a eu plusieurs arrivées devant la montée des marches, en bas. Le seul engin qui retient mon attention n'a toujours pas ouvert une portière vers notre dimension. Une voiture diplomatique, est-ce que c'est comme une valise diplo que même les flics n'ont pas le droit d'ouvrir ? Le véhicule reste stationné avec les phares, au tréfonds de la parcelle privative, pendant que les autres voitures tournent en rond devant des barrières sans pouvoir accéder aux secrets de l'arrière-boutique. Une femme à cheveu court est seule derrière le volant. C'est tout ce que j'en sais. Je n'ai pas eu le temps de la voir correctement avant qu'elle ne se gare à l'abri. Elle doit attendre quelqu'un dans sa Porsche, un SUV coûteux mais très commun, rien d'exceptionnel pour un spotteur. Moi c'est le contenu qui m'affole. Je pensais qu'un casino était le comble de l'opacité. Je n'avais jamais réfléchi au vide légal des consulats et des ambassades. Une chambre obscure qui se déplace dans notre espace public tout en se maintenant au-dessus des juridictions des pays qu'elle traverse, ça laisse quand même beaucoup de place à l'imagination. Surtout ici. Pourquoi la conductrice ne descend pas ? Par moment une tache bleutée apparaît derrière les vitres, mais les jumelles ne sont pas faîtes pour observer la nuit. La petite lueur d'écran se noie entre la clarté des phares et celle des illuminations sur la façade du casino. Peut-être qu'elle est chauffeuse, pour un riche client, ou pour quelqu'un qui travaille là. Qu'elle est une sorte de livreuse... ? Avec les privilèges spéciaux d'un véhicule inviolable comme ça, il pourrait y avoir n'importe quoi à l'intérieur. Des trucs illégaux. Je ne peux pas m'empêcher de penser à des choses compliquées. C'est vrai que j'ai un petit côté paro, la psy l'a quand même bien compris. Pourtant ça serait pas surprenant que des bails sombres aient lieu aussi chez nous, même si on est dans un trou à vaches. Les rubriques judiciaires dans les médias sont pleines d'histoires de détournements de fonds et de corruption, jusque dans les petites mairies. Si je me souviens bien, il y avait eu une histoire il y a quelques années, un fils de diplomate qui déplaçait de la drogue dans ses valises protégées par le secret diplomatique.

Le vent qui me glace le nez, ça me sort de mes fantasmes. Je remonte le cache-cou jusque sous les paupières, et je me souviens que je suis en train de brûler le temps en me racontant des histoires. Qu'il va falloir faire un choix pour y mettre fin. Je me souviens aussi qu'en calculant vite fait le ratio, j'ai plus de chances d'être déçu qu'émerveillé, sur ce tapis de réalité. J'espionne ce parking comme s'il allait y avoir un bouquet final, mais ce qui va vraiment se passer d'ici quinze ou vingt minutes, c'est que j'aurai à peine le temps d'apercevoir un dénouement sans intérêt. Encore un. Quelqu'un va sortir du casino et monter en vitesse dans la Porsche. La voiture disparaîtra avec son contenu, sans rien me raconter. Et ensuite, je serai de nouveau tout seul dans la nuit.

J'ai froid. Encore un peu de patience avant de lancer ma pièce pour décider. Même si je ne vois rien d'excitant ce soir, je veux rester jusqu'au bout de ma fiction diplomatique. Je me suis accroché à cette plaque d'immatriculation CD, je dois la voir disparaître sur la route pour pouvoir passer à autre chose. C'est rare d'être encore accroché par quelque chose. Alors j'attends, et je baisse les jumelles. Je visualise l'intérieur des lieux. Dedans il y a la moquette rouge partout. Le bar, sur la gauche, où même les péons comme moi peuvent se prendre pour quelqu'un. Je suis rentré une fois pour voir, au début. Au fond il y a la salle de jeu, barrée par des portiques. Il faut s'adresser à la caisse pour aller plus loin, un grand comptoir où une femme en chemise col blanc reste assise toute la journée à attendre. On ne visite pas le royaume des machines à sous sans acheter d'abord des jetons. Le bar est accessible librement, mais si on tourne en rond sans dépenser d'argent, un vigile s'approche. J'avais imaginé boire un verre là-bas juste pour entendre des conversations de bourges du coin qui se donnent des rendez-vous d'affaires. Sauf qu'une seule conso c'est mon budget des courses pour la semaine. Et puis quand le mec en costume est venu me demander si j'attendais quelqu'un, j'ai eu l'impression d'être un clochard avec mes vêtements de tous les jours.

Oh... Il y a du mouvement au fond du parking privé. J'attrape les optiques grossissantes qui pendent à mon cou. Un éclairage s'est déclenché à l'arrière du casino. Une porte de secours qui s'ouvre perpendiculaire. Elle reste maintenue dans cette position, le panneau gris face à moi, mais je vois personne. L'éclairage extérieur est tellement fort qu'on devine le grain du crépi sur le mur. J'attends celui ou celle qui va se précipiter dans ce théâtre. D'une seconde à l'autre... Allez. Alors, qu'est-ce que vous attendez ?

[CC BY]

 
Lire la suite...

from P É O N A G E

Quand j'étais petit, Mamie me montrait comment on prépare un affût. Ne pas se faire voir, observer derrière un interstice. Silencieux, immobile. On consultait les illustrations ensemble dans le guide des oiseaux avant de partir, j'apprenais par cœur ceux que je voulais voir. Le Milan royal avec sa queue en V et ses couleurs rousses. Le chardonneret élégant, bout du bec teinté et les ailes noires tachetées de blanc. Mes volatiles ont des carrosseries mates et des options luxe maintenant. Toujours les fesses contre le banc en haut de la butte, dans le bouquet d'arbres touffus, je zoome sur les lumières des phares. Personne ne me voit.

Des phares qui font un demi-tour sur le parking lointain, avant de s'immobiliser. Pas encore un oiseau rare. Juste une berline allemande à grosses jantes que les jeunes d'ici conduisent le permis à peine obtenu. Le moteur tourne, je vois des vapeurs surnaturelles dans les halos xénon du parking. Personne ne descend. On est le 10 du mois. La paye tombe le 8. Je risque d'en voir des communs, avant de tomber sur les ultra-rares. Mais si je suis patient... Autour des casinos il paraît qu'on rencontre forcément un jour des gens exceptionnels. Dangereux. Des ultrariches, des mafieux. Des politiciens corrompus avec les oligarques des pays bannis. C'est comme une loi physique. Là où il y a des jeux d'argent, ça attire les grands forceurs et les bourbiers. En squattant mon banc j'aimerais en voir un seul, de vrai spécimen. L'élite, il paraît qu'elle existe même si on ne la voit jamais. Ceux qui vivent dans des circuits séparés, avec domestiques, qui ne font pas les courses parce qu'ils ont des cuisiniers et qui ne mélangent pas leurs enfants avec nous, aux grandes écoles privées. Comme un monde parallèle. Mais ils n'ont pas encore aboli la rue, les riches. Il faudra bien qu'on se croise à un moment sur le ruban qui conduit jusqu'aux casinos.

Les phares s'éteignent au loin. En quelques secondes, trois jeunes gars pas assez bien habillés enjambent la dizaine de marches couverte d'un tapis rouge, avant de disparaître derrière les portes vitrées. C'est allé très vite. Comme avec les bêtes, il faut être attentif pour ne pas rater des apparitions. Je ne sais pas combien de temps je vais tenir, seul dans la nuit. L'excitation d'espionner un autre monde m'électrisait, mais l'immobilité, la solitude, il va bientôt faire froid et flemme. Je ne sais plus ce que je cherchais vraiment en venant ici. Encore quelques véhicules à scruter, avant de me résigner. Encore quelques tours de roulette.

Mamie me manque un peu. Elle avait tellement de choses à me raconter. De l'inventivité, quand on s'ennuyait, des solutions à tous les problèmes de la vie. Mes problèmes sont trop différents aujourd'hui... Qu'est-ce qu'elle me répondrait ? Que c'est pas grave si je préfère me raconter le monde autrement ?

De la lumière là-bas. Impossible de s'ennuyer longtemps autour des machines à sous. Il y a un SUV noir qui s'avance lentement. Jusqu'au bout du parking, vers la barrière pour les employé⋅es. Ses phares s'immobilisent devant le portique. Le temps de déchiffrer l'immatriculation. Je crois que ça commence par CD... Corps Diplomatique ? La barrière se lève, le carénage glisse puis s'immobilise, en retrait, dans le périmètre interdit à toute personne étrangère au service. Les phares qui s'éteignent. Mais personne n'apparaît. Un canal invisible me raidit la nuque. Je ne sens plus le froid. Mamie dirait peut-être : Il y a une différence entre vouloir s'amuser et chercher les ennuis.

[CC BY]

 
Lire la suite...

from P É O N A G E

Des phares qui se croisent en tournant comme des bestioles. Toutes les cinq minutes. La diffraction dans les lentilles ne donne pas une image aussi claire que le jour, mais sous la lumière des lampadaires je vois la couleur de leurs vestes quand s'ouvrent les portières. Je devine aussi les plaques d'immatriculation. Presque distinctement. Ma psy ne comprendrait pas. Je dois lui cacher cette nouvelle occupation. Elle n'en voit que les conséquences positives, se félicite de mes progrès, parce que lâcher prise ça aide à arrêter de stresser. Je lance des pièces pour ça. Elle a beau répéter que ma volonté est un moteur ou une voile, on n'est jamais aussi heureux qu'en abandonnant totalement le contrôle. C'est bien ce qu'ils veulent non ? Les patrons et les référent⋅es emploi, prêt⋅es à m'envoyer dans n'importe quel dépôt qui pue le gasoil. On n'a jamais eu le contrôle de nos existence. On n'a même pas notre mot à dire sur les chiffres d'affaire dont on ne voit jamais la couleur, au SMIC. Si je dois lui révéler ce que je pense vraiment à la psy, elle va froncer un sourcil en se penchant vers son bureau, avant d'asséner une de ses vérités qui me renverront des années en arrière. Et puis elle sera obligée de noter, qu'il n'y a “pas d'amélioration”.

Autant faire semblant.

Le casino construit sur une zone naturelle protégée. Les phares comme des lasers dans la nuit. Le Maire est un arnaqueur, mais ses fraudes sont légales, alors ça ne dérange pas ma psy. À la place de la zone humide, une tourbière qui abritait des plantes carnivores et d'autres espèces protégées, il a autorisé le bétonnage. Il a suffit d'une seule zone “éco-responsable”, sur un bout de parking perméabilisé, pour valider tout le carnage. Subventionné par la région et l'État. Maintenant les allées et venues de voitures ont remplacé le bruit des insectes rares.

Leur roulette est truquée, alors j'utilise la mienne. On observe les immatriculations comme des oiseaux. J'ai les jumelles longue distance que mamie utilisait. Je les regarde. Voyeur de leur gaspillage, beaux manteaux, voitures grande gamme, pour aller jeter de l'argent. Bien sûr que ça pose des questions leur vie privée, mais ma référente Parcours Emploi Renforcé m'a recommandé de ne pas penser à ce qui était en dehors de mon contrôle. Au lancer de pièces, je joue tout. L'avenir, l'éthique, la morale. Ça remet de l'appétit au quotidien. Entre deux convocations pour me faire menacer parce que j'ai encore refusé une offre d'emploi.

[CC BY]

 
Lire la suite...

from Léonard Urban

I’ve been using the Slimbook EVO 14 for a few days now, and here are my impressions. This is also a test of writefreely—let’s see how it goes! 😉

My Old Laptop

As a computer science (and biology) student, I mainly use my laptop for taking notes and doing homework. Beyond that, I’m a Linux hobbyist and enjoy programming for fun.

Before switching to the Slimbook, I used a Lenovo Ideapad C340 14'' Intel with 1TB of storage and 16GB of RAM. While it served me well for about six years, several issues became hard to ignore:

  • Screen quality: The 1080p resolution was too low for comfortable text reading, and the viewing angles were poor.
  • Battery life: The 40Wh battery degraded over time, lasting only about 1.5 hours in power-saving mode by the end.
  • Graphics performance: The integrated GPU struggled with anything beyond lightweight games (like Minecraft at 720p) and limited external 4K displays to 30Hz.
  • Build quality: The chassis cracked in places, and I had to use duct tape to hold the hinges together.
  • Keyboard failure: An entire row of keys stopped working, rendering the laptop unusable without an external keyboard.

Choosing a New Laptop

My new laptop needed to meet the following criteria:

  • Better performance
  • More RAM
  • Improved screen
  • Under 1,000 CHF
  • Good Linux support
  • From a European company (here’s why)

These last two points narrowed my options to Tuxedo and Slimbook. Since I carry my laptop all day, I wanted something under 15''. This left me with the Slimbook EVO and the Tuxedo InfinityBook—identical machines in terms of specs. I chose the Slimbook EVO because it was cheaper and came with GNOME preinstalled.

Review

Hardware

The Slimbook EVO feels well-built, especially compared to my old laptop. The aluminum chassis is sturdy and premium. The screen is a significant upgrade: better viewing angles and resolution, though the scaling is a bit awkward. At 100%, everything is too small; at 200%, too large. Fractional scaling works, but may affect battery life. The 120Hz refresh rate is smooth, but I disabled it to save power—it’s not essential for my workflow.

The only downgrade from my previous laptop is the lack of a touchscreen, but since I use an external drawing tablet, it’s not a dealbreaker.

Performance-wise, this laptop is a breath of fresh air. It boots in under five seconds, handles Minecraft at full resolution (with shaders!), and supports 4K displays at 60Hz. My model has 32GB of RAM and 500GB of storage. The extra RAM is a relief, and while the storage is half of what I had before, 500GB is more than enough for my needs.

Software

Buying from a Linux-first vendor means most drivers are preinstalled. However, I decided to install Ubuntu 25 from scratch—perhaps not the smartest move. The installation went smoothly, but I had to manually install a few packages, like the Ethernet driver (guide here).

Facial recognition via howdy doesn’t work yet, as it depends on a library not yet ported to Ubuntu 25. For now, I’ll stick with typing my password.

I also replaced Slimbook’s slimbook-battery (which uses TLP) with power-profiles-daemon for better GNOME integration. I might revisit this later to see if TLP offers better battery life.

Speaking of battery, I capped the charge at 80% in the BIOS to extend its lifespan. It’s reassuring that Slimbook sells replacement batteries, which could be useful down the line.

Final Thoughts

I’m happy with my purchase and would recommend the Slimbook EVO 14—especially if you value Linux support and European manufacturing.

Note: This text was re-phrased with AI (Le Chat by Mistral.ai to be precise).

 
Lire la suite...

from Café histoire

Ce jour, j’ai reçu 7 précieuses merveilles dans un imposant coffret. À une époque lointaine, on parlait de galettes.

J’ai déposé une première galette sur ma platine cd. En fait, la dernière « Perfect World », puis la première galette « LA Garage sessions ´83 », histoire de commencer par la fin, puis revenir au début de ce cadeau musical proposé par Bruce Springsteen avec son « Tracks II: The Lost Albums ». Du bel ouvrage.

Plus tard, dans la nuit, j’ai déposé une troisième galette, le deuxième album de fait de cette collection, « Street of Philadelphia Sessions ». C’est d’une beauté lancinante et déchirante jusqu’à la profondeur de l’âme.

Je reste scotché à ce morceau « We fell down »

WE FELL DOWN In the dream everything had come undone / I sat in the kitchen and listened to the refrigerator hum / Three A.M. had come and gone / You walked in I knew by that dress you had on / We fell down... we fell down.../ I shoulda known when I asked where you'd been and I heard you lie / We fell down... we fell down... / That was just your way of saying goodbye // We got a book with pretty pictures all in a row / There's only. one missin' baby, that I know / That's the one of you and I / The one where we're lookin' each other in the eye / We fell down... we fell down.../ You said things get lost no matter how hard you try / We fell down... we fell down... / That was just your way of saying goodbye // I woke in the mornin' cold and gaspin' for air / Everything seemed broken beyond repair / The party ribbons and balloons had fallen to the floor / Along with the beautiful costumes we wore // I get up in the mornin', get dressed for work /1 comb my hair and button my shirt / I walk home neath a sky hard and blue / These are the things that I've gotta do / Since we fell down... we fell down.../ And I asked if you loved me, you said, of course you did and sighed / We fell down... we fell down... / But I knew that was just your little way of sayin' goodbye

Nous sommes tombés Dans le rêve, tout s'était défait / Je me suis assis dans la cuisine et j'ai écouté le bourdonnement du réfrigérateur / Trois heures du matin était venu et parti / Tu es entrée, je le savais par cette robe que tu avais / Nous sommes tombés... nous sommes tombés... / J'aurais dû savoir quand j'ai demandé où tu étais et je t'ai entendu mentir / Nous sommes tombés... nous sommes tombés... / C'était juste ta façon de dire au revoir // Nous avons un livre avec de jolies photos dans une rangée / Il n'y a qu'un seul bébé manquant, que je connaisse / C'est celui de toi et moi/ Celui où nous nous regardons dans les yeux / Nous sommes tombés... nous sommes tombés... / Tu as dit que les choses se perdent, peu importe à quel point tu essayes / Nous sommes tombés.. nous sommes tombés.. / C'était juste ta façon de dire au revoir // Je me suis réveillé dans le froid du matin et j'ai haleté à la recherche de l'air / Tout semblait cassé au-delà de toute réparation / Les rubans et les ballons de fête étaient tombés par terre / Avec les beaux costumes que nous portions /Je me lève le matin, je m'habille pour le travail/Je me peigne les cheveux et boutonne ma chemise / Je rentre à la maison / Sous un ciel dur et bleu / Ce sont les choses que je dois faire / Depuis que nous sommes tombés... nous sommes tombés... / Et j'ai demandé si tu m'aimais, tu as dit, bien sûr, as-tu dis et soupiré / Nous sommes tombés... nous sommes tombés... / Mais je savais que c'était juste ta petite façon de dire au revoir.

Merci M. Springsteen.

Pour une critique musicale de ce coffret, je vous invite à lire «The Lost Albums—Tracks II»: les 7 rédemptions de Springsteen, le Boss perfectionniste | Le Devoir.

Tags : #AuCafé #musique

 
Lire la suite...

from Ori raconte

Le non-respect de la vie privée

Meta sait tout de vous :

  • Votre nom, courriel, n° de téléphone, âge ;
  • Vos clics, réactions, contenus créés, publications, photos, messages ;
  • Vos interactions avec le contenu, les publicités regardées ou cliquées ;
  • Vos liens avec vos amis, ceux qui vous suivent, et l’utilisation de leurs produits ;
  • Vos appareils, vos applications installées, votre navigateur ;
  • Votre adresse IP, et donc votre localisation ;
  • Les sites que vous visitez, les applications utilisées, les jeux auxquels vous jouez ;
  • Combien de temps vous passez sur chaque plateforme ;
  • Les n°, noms, et adresses emails de vos contacts ;
  • Sur quels points d’accès Wi-Fi, sur quelles antennes mobile et bluetooth vous vous êtes connectés ;
  • La localisation de vos photos, les personnes affichées.

Ces données sont utilisées et revendues pour :

  1. Mieux cibler les annonces publicitaires ;
  2. Entraîner des intelligences artificielles ;
  3. Le renseignement commercial ou politique.

Et souvenez-vous :

Lorsque vous dites « le droit à la vie privée ne me préoccupe pas, parce que je n'ai rien à cacher », cela ne fait aucune différence avec le fait de dire « Je me moque du droit à la liberté d'expression parce que je n'ai rien à dire », ou « de la liberté de la presse parce que je n'ai rien à écrire ».

Edward Snowden.

Une porte d’entrée pour la malveillance

Adoptées à grande échelle, mais très peu modérées, ces plateformes sont utilisées pour diverses arnaques, phishing, voire pour prendre le contrôle de l’appareil.

Publicités et algorithmes

Vous ne contrôlez pas ce que vous voyez, car des publicités sont omniprésentes dans votre flux. En conséquence vous voyez des publications que vous ne souhaitez pas, et vous ne voyez pas certaines publications de vos contacts et des pages que vous suivez, car des algorithmes l’ont décidé ainsi.

Quelles alternatives ?

  • Pour Facebook, créez-vous un compte sur une instance Mastodon (par exemple, sur tooting.ch ou swiss.social).
  • Pour Instagram, créez-vous un compte sur une instance Pixelfed (par exemple, sur pixelfed.ch).
  • Pour WhatsApp, si vous êtes intéressés par les fonctionnalités avancées, telles que les groupes, les chaînes… alors installez Telegram. Sinon, installez Signal.

Ensuite, avertissez vos contacts de vos choix et convainquez-les de vous rejoindre. En quelques temps, vous vous rendrez compte du bonheur de votre indépendance, de la joie de pouvoir suivre ce que l’on veut, sans pollution publicitaire et sans risque.

 
Lire la suite...