During the summer sales on AliExpress I decided to buy 16 LiFePo4 cells, since I could save something on the price. The above is what I chose, because the price was very good and it had plenty of positive feedbacks of which the following is but a sample.

I received the packages about 9 weeks after the order, and when I unpacked them, the surprise…

The terminals were not just worn… but in some cases, actually destroyed, the seller had placed new male terminals inside the female receptacles; the cells were all swollen on arrival.

I immediately sent a disappointed message to the seller, to which they replied:

I mean… really?

After this reply, I followed with a long series of messages to say that I had to test the cells further, to decide the amount of refund I needed to ask, and that please I didn’t want to be treated like an idiot.

So, the testing started:

I used a JK BMS, a 100A max current model, with 0.6A balancing current, and a 5.5KW Hybrid Inverter connected to the mains to charge them.

Connections were obviously temporary while I tested, charging was set to 58V, and float to 54.4V.

Soon I noticed a few cells ran away with their voltage, with a delta V reaching quite high values of 300mA, and the BMS kept interrupting the charge until it wasn’t actually charging anymore, I’m talking about a few seconds of charging followed by a few minutes of cooldown.

After this first charge I left the pack alone, letting the BMS do the balancing as best as it could for the night and the whole following morning, and I attached a 2000W heater to the hybrid inverter to test the capacity…

A whopping 128AH capacity (less than 50% of declared) reported by the BMS before one of the cells repeatedly hit the lowest voltage, making further discharge impossible, and needing to disconnect and reconnect the battery leads from the inverter, otherwise it couldn’t start because of a short circuit detected by the BMS. A royal pain.

So this time I tried charging again with the hybrid inverter, after which I intended to to a top balance with a couple of bench power supplies…

The usual #15 and #16 cells kept stopping the BMS because of overvoltage, so I made two large parallel setups, 10P for the 10A power supply, and 6P for the 5A power supply, and left it for a couple of days, after which I built the series again and started charging once more, this time helping the balancing manually, by using a contraption made of 4 parallel 2ohm resistances submerged in water to cool them down, to drop the voltage on the worst cells, many many times… only to repeatedly hit the overvoltage limit on the BMS for #15 and #16 no matter how often I fixed their voltage with the contraption.

Not only this, but the cells became even more bloated after only a couple of charge cycles!

Then the idea came to me, set #15 and #16 in parallel! It would become a 15S battery, still with a usable voltage by the inverter, and maybe I would make up for the limited capacity of the last two cells.

Yeah, right.

Even like that, and even while using the contraption to cut down the voltage, repeatedly, #15 and #16 in parallel would STILL trigger the overvoltage protection.

Being desperate at this point, I then added #5 to the parallel arrangement since it was the one always jumping higher with the voltage… and the 3 cells in parallel at the end seemed to hold it, while the inverter could still manage with the voltage of a 14S, until YET ANOTHER cell started triggering the overvoltage protection; keep in mind the contraption was still being used to taper the overvoltage on single cells.

Then I said, to hell with it, let’s restore the 16S and now also let’s play a harder game, by charging single cells at the same time with the two bench power supplies.

I played wack-a-mole this way placing the alligator clips here and there depending on where the BMS app told me the lowest voltage cells were, until I got fed up with it.

Currently, I rebuilt two parallel 10P and 6P strings to charge once more overnight with the power supplies, after which I’ll try my Atorch DL24 to test the cells and determine the internal resistance of each.

There are still almost 20 days to go before buyer protection ends, but I cannot endure this much longer. I need to make an estimate of the refund I have to ask.

….

Continuing from where I left off, I made a single chain of 16 parallel cells, and applied the power supplies at both ends, and took a long time top balancing to 3.6V until the current from the bench supplies was negligible:

I then used the builtin function of the Atorch DL24 battery tester to measure the internal resistances of all the cells, by running them at 0.5A for 1 minute, and noting down the last value the DL24 showed for internal resistance right before the minute was over:

The measured resistances (in milliohms) were as above, with the smallest and largest values reporting the highest current the cell could withstand. Not very good values, at all.

I once again assembled the 16S configuration, and the bloating got even worse:

I had by then also labeled each cell with an identifying number.

I waited overnight to let the cells “rest”, and this was the result:

Then I started once again the  discharge test:

I attached the heater to the now top balanced cells expecting great results!

Discharged overnight until BMS killed the process because of cell #3 in undervoltage protection, rebooted the inverted in the morning to try and squeeze out a little more, still under 170AH! And this time, you can see how all the other cells are still around or below 3.1V, which means that they are pretty much depleted anyway, given this is the discharge curve of a LiFePo4:

I marked the 3.1V SOC for the 3.6V charge voltage; this means that all those cells were already depleted anyway when #3 was going in protection, no more juice can be squeezed from the pack.

But I’m really thorough, so I did another full charge and discharge cycle, this time only using the inverter since the cells were already top balanced. As usual the charge stop because #3 hits the overvoltage protection, but all the rest are still basically 100% charged, as per image above (check the 3.4V mark); the discharge stopped also because of #3, but same as above, the others are still depleted at ~3.1V.

Less than 170AH it is, no doubt.

And for some interesting facts, during the following multiple-section recharge, the cells got really balanced:

From 0 to 1mV of delta! They are indeed a cozy bunch, except #3 which likes to spoil it for all the rest, but this pack is a 165AH pack , NOT a 280AH one.

What’s more curious, the seller, even after giving proofs of the defect, started asking me to test a single cell instead….

At this point, I don’t think I’ll follow this request, as it makes no sense to me and I don’t want to waste time, and also unbalance all the set, since by testing just one, after this I will have to do yet another top balance with all the 16 cells in parallel. No thank you. It won’t help anything anyway.

I did I third discharge/capacity test, and results are clockwork at 166AH:

No more tests, it’s settled, I’ll open a dispute with this data, there are plenty of proofs.

UPDATE: I did decide to test a single battery just for fun, I picked the best out of the bunch, #6 which you can see above that has the lowest voltage when pack is charged, and the highest when pack is discharged.

I singled #6 out and topped it to 3.61V, then used Atorch DL24 to test it down to 2.7V (why no 3.65-2.5? Because it makes no sense stressing the battery for, what, 1% more capacity?)

Here are the results.

Best cell is 186Ah, a far cry from the promised 280Ah.

I told the seller the results of this test, I also opened the dispute.

The seller’s response to the private message was “you didn’t test in standard conditions” (what are standard conditions? Using their fairy testers that report double the real capacity?), and response to dispute, where I posted, among others, a picture with clearly visible destroyed electrodes, bulging, and crappy covering, was “We only provide brand new batteries, bulging is because of incorrect test conditions and because buyer did not compress the cells”.

DOUBLE-U TEE EF.

This person has no trace of shame in this world.

I am currently in advanced dispute with the seller, and waiting for AliExpress to make a decision based on my indisputable video proof (at least I think), there are hidden scratched QRs under the replaced battery covers showing they were ONCE 240AH (not even 280AH), but I couldn’t resist yelling at the person I’ve been talking with:

# Sync OneDrive and Dropbox to more than 3 total devices

Disclaimer: this will be wonky, probably you will not like it, but it’s free, so what do you have to lose.

Facts: Dropbox and OneDrive are both free; Dropbox allows only up to 3 paired devices at all times (no idea about OneDrive).

Let’s say you want to let a fourth device access Dropbox for free, at least (or even better yet) for just a subset of files in your dropbox.

Enter OneDrive.

Install and configure it, then make use of Windows mklink command to create symlinks, by opening an elevated command prompt from the start menu (open start menu, type “cmd” and right click on the command prompt link, choosing “Run as administrator”), then cd into OneDrive’s root folder, and type:

mklink /D things path\to\Dropbox\folder\you_want_to_share

from now on, OneDrive will start uploading the contents of the Dropbox folder you specified, so they will be available to your other PCs’ OneDrive installations past the limit of 3 concurrent devices.

I tested that an empty text file created in the 4th PC’s OneDrive folder will appear in the Dropbox+OneDrive PC’s Dropbox folder, but I noticed that edits of this empty file don’t really propagate… maybe it’s just a matter of time? Also, deleting that file in the Dropbox+OneDrive PC will not delete the file in the 4th OneDrive only PC.

This is just from a few minutes of testing, I wanted to share the news.

# Fix crontabS fdopen Permission denied

Somehow my Raspberry started giving me this error whenever I tried crontab -e from a user account (sudo crontab -e worked fine for root contab, or sudo crontab -e -u username for offending user).

I searched on the internet several times, trying to fix permissions on crontabs folder, without any joy, until this post finally helped me:

sudo chown root:crontab /usr/bin/crontab
sudo chmod 2755 /usr/bin/crontab

and I was able to edit user’s crontab from user’s CLI.

# Boot Btrfs root partition with Raid1 on Raspberri Pi

https://feldspaten.org/2019/07/05/raspbian-and-btrfs/

and

https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=319427

and I decided to summarize the process here, after extensively testing on a Raspberry Pi 4 with 8GB of RAM, and a 64bit OS; I might extend this guide to include setting up a Raid1 with a second disk (spoiler: I already did, down at the end of this page).

WARNING
I suggest testing this procedure on a pendrive where you flashed the image of a raspberry pi os distribution, WITHOUT using apt update & full-upgrade for two reasons:

1. nothing bad will happen if things go wrong, since it’s not a production environment
2. you’ll be able to test the kernel update automation AFTER you completed all the steps, by running the apt update && full-upgrade commands

Install requirements and edit needed modules:

sudo apt install initramfs-tools btrfs-tools
# use btrfs-progs if btrfs-tools has "no candidate"
sudo nano /etc/initramfs-tools/modules

Add the following lines to the file and save:

btrfs
xor
zlib_deflate
raid6_pq

Create the initramfs in /boot partition and edit config.txt:

sudo mkinitramfs -o /boot/initramfs-btrfs.gz
sudo nano /boot/config.txt

adding the following line up top and save:

# For more options and informations see
# http://rpf.io/configtxt
# Some settings may impact device functionality. See link above for details

initramfs initramfs-btrfs.gz

For good measure, check if rebooting the system is succesful. Then sudo poweroff and place the disk (SD, SSD, pendrive) on a linux PC (or just reboot the same Raspberry Pi with a different media you prepared, like an SD card or a pendrive, leaving the disk attached) , and, let’s say the device is recognized as /dev/sdb:

sudo fsck.ext4 /dev/sdb2
sudo btrfs-convert /dev/sdb2
sudo mkdir /mnt/rootfs
sudo mount /dev/sdb2 /mnt/rootfs

We’ve just checked if the existing ext4 rootfs is clean, then we converted it to btrfs (it will take quite some time to create the ext2 image to make rollback possible), then created a mountpoint and mounted to it the just converted btrfs root partition.

We now need to update the fstab in this partition so the system will correctly mount at boot:

sudo nano /mnt/rootfs/etc/fstab

Correct the root line (/) by replacing ext4 with btrfs, and make it sure it ends with two 0‘s to disable fsck on it (btrfs has its own builtin filesystem checks, and fsck might return unwarranted errors).

Also, correct /boot/cmdline.txt in the boot partition by replacing, again, ext4 with btrfs, and fsck.repair=yes with fsck.repair=no.

At this point, placing the drive back on the Pi (or removing the other booting media and leaving just the disk) and booting will take you in a btrfs rootfs.

BEWARE navigators: this was my major gripe, as without anything else added to the procedure, a kernel update will be followed by a useless system at the next reboot, because the initramfs won’t be recreated.

User dickon on raspberrypi forums was a great help in the following procedure.

You need to create a script to automatically update initramfs in /boot after a kernel update, so here it is.

sudo nano /etc/kernel/postinst.d/btrfs-update

Insert this code in the script (this will work with a 64bit OS, make sure kernel8.img is the correct filename, you can check against the existing file in /boot, otherwise change accordingly):

#!/bin/bash
if [ "x$2" != "x/boot/kernel8.img" ]; then exit 0 fi echo ============ UPDATE INITRAMFS ============== mkinitramfs -o /boot/initramfs-btrfs.gz 0,86 EUR echo ============ UPDATE COMPLETED ============== then make sure it is executable, and has the same permissions of the other files in the same folder: sudo chmod 755 /etc/kernel/postinst.d/btrfs-update At this point, the system will (should) update the relevant initramfs right after each kernel update, freeing you of the hassle of remembering to do it by hand, or risk having a useless system after the next reboot. It is a good idea to disable swap, since btrfs won’t be able to host a swap file anyway: sudo systemctl disable dphys-swapfile.service or alternatively, for a more aggressive approach that will remove the swapfile capabilities entirely: sudo dphys-swapfile swapoff sudo dphys-swapfile uninstall sudo update-rc.d dphys-swapfile remove sudo apt purge dphys-swapfile In case you have a spare SSD lying around (who doesn’t) and you want to leverage the advantages of both redundancy and concurrent read speeds, then you can easily use btrfs innate capabilities for this. You should mirror the partitioning of the system disk on the second SSD (unless there is a large disparity in size), and when that’s done, like detailed here, follow these steps: sudo btrfs filesystem show will confirm that the partition assigned to the rootfs mountpoint is the one you just converted a while ago. Let’s assume the partition you want to mirror the rootfs to is /dev/sdb1: sudo btrfs device add -f /dev/sdb1 / will assign it to the rootfs mountpoint, which you can confirm by re-issuing:  sudo btrfs filesystem show that will show the second drive together with the first; you will then instruct btrfs to proceed with the actual mirroring of the data: sudo btrfs balance start -dconvert=raid1 -mconvert=raid1 / which might take some time depending on the amount of used space on the partition. From now on, you will be able to add even more drives, or remove failing ones to substitute them, and there is plenty of resources online that you can search for without me having to detail them all in here. # HOCl Hypochlorous Acid using salt water electrolysis I have published several videos on youtube about HOCl production, the older one, the newer one, and the italian one, even older and uglier. Yet another might be in the works, as the vat model I’m currently using is different from the one in the latest video, and I plan to build another improved version of that. Anyway, I’m creating this post because one user on youtube made several very interesting questions that deserve to be answered here as well. I am really confused after many days of research of this topic. I have really doubt if it is possible to get HoCl by simple electolysis of NaCl, but on the other hand does the USA companies lies about theyre commercial products? Or it is really so important to keep very specific conditions (size of electrodes, voltage, amperage, etc.) I have made many of attempts with concentration of salt vinegar, duration of electrolysis. I haven’t got enough big electrodes (now ordered from aliexpress similar as yours) and I haven’t got ppm tester so I can’t evalueate the final product. When I used a small amount of salt and vinegar and let electrolysis almost 2 hour (because of weak power supply, small electrodes 1 lite of solution) it doesn’t smell so intensive by chlorine like before when I used much salt. But if I tried to immerse cloth to this solution it bleaches it a little. So I am not sure if it should be HoCl or not. HoCl should smell so strong like NaOCl or not? It is the right technique to rise the time of electrolysis when you have small electrodes? What happens to solution if you let it run too long? To which I replied: you pose good questions. I am not the guy for you as I can only answer by experience, not by knowledge. My solution has not showed to bleach tissues, given I have never submerged a cloth inside it, but I spray many dressed people all day long when they access a certain area, been doing it for a year, and noone complained yet. The best way I can describe the smell of my solution after it’s been for a few hours inside the reservoir of the pressure painter I use to spray it, is “swimming pool changing room”, if you know what I mean. The concentration of HOCl in the final solution is a result of: pH of the solution (optimal is 5 if I remember correctly, yet 6 is pretty much the same), amount of electrical current (which itself is proportional to voltage, electrodes area, electrodes distance, and amount of electrolytes in the solution, that is, salt), and amount of salt (so how much salt you place in there will speed up the reaction twice, but will also leave a larger salt residue when the solution dries up). By the way, regarding the evidence that this method really works, there’s plenty of papers where it’s detailed that electrolysis is the simplest way to obtain HOCl, albeit not the most efficient. Running the electrolysis for too long will warm up the solution because of Joule effect (possibly degrading the HOCl which is in itself unstable), and increase the amount of corrosion the anode will go through. # Convertire automaticamente da FLAC a MP3 Scrivo per riferimento personale questa guida, che traggo da un post semplice ed efficace, e che per utilità generale traduco in italiano e inserisco nel mio blog a scopo di “backup”. I file FLAC sono lossless, cioè fedeli alla qualità del CD originale. Ma l’orecchio umano non è perfetto, quindi fatto salvo tu sia un audiofilo investito di poteri extrasensoriali, la conversione a MP3 ti darà la stessa medesima qualità percepita ad una frazione dello spazio occupato. Per questo, da Linux, o da Ubuntu installato su Windows 10 tramite WSL (qui una guida), installare i codec LAME e FLAC con: sudo apt install lame flac E quindi dopo essersi spostati nella cartella contenente i file FLAC che si desidera convertire (su Ubuntu sotto WSL, il percorso è /mnt/<lettera drive>/percorso/della/cartella), eseguire il comando: for f in .flac; do flac -cd "$f" | lame -b 320 - "${f%.}".mp3; done che per ogni file FLAC presente, crea una versione MP3 a bitrate costante di 320kbps. Potete cambiare il numero da 320 a un valore inferiore per ridurre il bitrate, o sostituire l’intero blocco -b 320 con -v, per un bitrate variabile, ma se lo fate siete degli zotici e non meritate di ascoltare musica. Scherzo dai. # Dritte per un decoupage di fumetti su tavolo Questo articolo è tanto divulgativo quanto di riferimento personale, infatti dopo le fatiche affrontate durante un progettino in corso d’opera ho pensato che sarebbe meglio metter nero su bianco quello che ho imparato. In ordine più o meno sparso: • superficie più pulita possibile, se si tratta di legno appena levigato accertarsi che sia stata rimossa la polvere quanto più possibile • miscela 50/50 vinavil e acqua, stendere sul piano senza lesinare, deve esserci la possibilità di “spremere” la colla da sotto la carta una volta applicata • connesso al punto precedente, se il piano è un legno poroso o appena levigato e molto “asciutto”, occorrerà stendere una quantità maggiore di base • usare un pennello per verniciare la colla, se il fondo è poroso verniciare leggermente anche il retro del foglio di carta da applicare • posare il foglio nella posizione desiderata, e usare una specie di spatola morbida per stenderlo energicamente spremendo via i residui di colla sottostanti, ho usato con successo una “linguina” in gomma di quelle adatte a impastare le creme nelle ciotole e versarle nelle tortiere successivamente • dopo il passaggio precedente normalmente la colla in eccesso passa attraverso il foglio di carta fino a bagnare la superficie superiore, ma nel caso ripassare delicatamente col pennello e poca colla • decidere sin da subito il tipo di disposizione, in ogni caso è preferibile iniziare in un punto ed estendersi da quello, piuttosto che applicare i fogli in punti separati e proseguire irregolarmente; la disposizione a griglia è più semplice e efficiente, giacché richiede il minor numero possibile di fogli, ma quella casuale, con i fogli in obliquo e parzialmente sovrapposti, seppur richieda più fogli, risulta normalmente anche più gradevole • nel caso vadano ritagliate parti di foglio, il risultato è sia esteticamente sia tecnicamente più piacevole se vengono piuttosto strappati lungo i margini (le fibre di carta frastagliata si prestano meglio all’adesione) • sei margini di alcuni fogli tendono ad alzarsi, è preferibile intervenire subito prima dell’asciugatura, sollevandoli finché non si avverte un minimo di resistenza, e applicando sotto, sia su piano che retro foglio, un po’ di colla aggiuntiva col pennello, stendendo bene nuovamente con la spatola • attendere l’asciugatura completa (asciutezza e compattezza ben avvertibili al tocco) per i passaggi successivi di colla, che dovrebbero contenere una percentuale maggiore di vinilica rispetto al passaggio iniziale • [varie ed eventuali da aggiungere a proseguimento del progetto] # Titanium backup doesn’t restore on latest Android version If you found the latest version of Titanium Backup (now almost one year old with no recent updates…) cannot restore your apps data anymore on Android 10, this solution was found in the comments on the play store, by Stranger Stunts, published on 9/12/20. Turn off “Verify apps over USB” in Developer Options, then turn off “Play protect” in the Play Store. I didn’t test it properly but I remember last time I had such a problem I found a similar solution in the same fortuitous way, and it worked, but I didn’t have the idea to save it somewhere. So I’m saving it on my blog for future reference. # Clone raspberry disk TO newer/larger disk/SD/SSD I was switching from a 120GB SSD on my Raspberry Pi 4, to a 240GB one. Found this and I cloned the command in the opening question: sudo dd if=/dev/originaldisk of=/dev/destinationdisk bs=4096 conv=sync,noerror where I used /dev/disk/by-id/... handles to make sure I was pointing to the correct SSD’s (otherwise, had I swapped them, a huge mess would happen). The resulting SSD was a perfect copy down to partition ID, so the cmdline.txt file under /boot/mounted from a FAT partition on the SD was starting the system off the new disk as if nothing happened. I just tested it for the inverse situation. On a Raspberry Pi 3, the running disk was a 240GB SSD, but it was pretty much wasted space since it was hosting a less than 4GB root partition, so I wanted to switch it to the 120GB SSD that I took out of the Raspi4. I ran the above command, and I allowed myself the luxury to just Ctrl-C out of it after the first 10GB had been copied over, because actually just 4GB of the disk were being used. Guess what, turned off the system, put the second SSD in place of the first, and the system booted perfectly. So, how do you check the progress of a running dd command, you might ask? Well, with the progress tool, naturally! sudo apt install progress first, and then, right after dd has started, sudo progress -wm This will clear the screen, and have the current status of the copy being shown and updated, while the copy is still running, so use of byobu (go search for that) is highly recommended. The sudo is there because dd was started as root, so progress won’t be able to access its status unless ran with same privileges. Disclaimer: using dd to clone a running disk might create inconsistencies where other running processes change the disk contents while the copy is running, and the resulting copy has part “old”, and part “new” content. Usually, this doesn’t matter, or might not happen at all if all the other processes access either tmpfs partitions or another disk, but in the end only you know what your system does, so thread with caution. # Get list of cases in a PHP switch statement Like the title says, you have a PHP script where a (supposedly long) case switch statement is placed, and you want to programmatically get a list of all the strings for each case. My use case is, I have a Telegram bot for my own private use, which does several actions, all different among themselves, when receiving user input from a specific account (mine). The command strings are predetermined, so I have a -long- list of cases like so: switch(strtolower($text)) {
case "blah1":
dosomething1();
break;
case "blah2":
file_put_contents($somefile,2); break; case "blah3": echo file_get_contents($someurl);
break;
// [...]
case "blah12":
exec('php somescript.php > /tmp/somescript.log 2>&1 &');
break;
}

I am adding new commands all the time, with the most different functions, and I might even forget some neat functions exist, so I wanted to implement a function where, in reply to a certain command, the bot lists all possible other commands (a --help function of sorts if you might).

They cannot be simply put inside an array, to be neatly listed at my pleasure, not with a useless excercise of my patience. Also, the listing functionality comes second, the first utility is semantical appropriatedness.

Let’s first say that there is no builtin function in PHP to get a list of cases in switch statement but you can still hack a function yourself.

The following solution is very ugly, but it will work on a simple code, and I would use this only if both of following conditions are verified:

1. You are the only user of the script (my telegram bot takes into account commands only if they come from my account)
2. the whole code in the script file basically revolves around the case switch and not much else

This scenario perfectly fits my case, so here’s what I did:

preg_match_all('/case \"([a-z0-9\s]+)\"\:/', file_get_contents(__FILE__), $matches); You then can use: foreach ($matches[1] as $casestring) { //... } or rather, as I actually did in the end, I simply returned: $reply=implode("\n",\$matches[1]);