[New + Review] YLP Unicorn 1.0 (1x18650, LH351D, backlit side switch, magnetic tail, TIR lens, ramping)

Default values “out of the box” are the same. Mid for main mode, High for additional one. However, they can be set separately for every UI (preset), because they are stored in memory separately.

No, I can’t. Every non-essential entity has been thrown out for the sake of simplicity of interface, while keeping flexibility. That’s why everything has to be done through slots.

Yes, exactly.

They are automatically saved to the workspace (Basic UI) in to EEPROM. Additionally, they can be copied to the one of three available presets. However, I want to change that logic to just four presets, which can be simply selected. Without any loads and saves in to workspace.

Stored in RAM. Only changes are written to the EEPROM and only during shutdown. That way load on EEPROM is reduced. Memory of modes wears the most, if it is used with ramping. One write operation for every shutdown, if brightness has been changed during operation. However, Unicorn has delayed shutdown, so when you switch something through shutdowns, it doesn’t count.
100’000 cycles – stated durability. In fact, it could be 3’000’000. I thing flashlight will be reduced to ash earlier.

I drink cider :).

Yes, I have estimated amount of #ifndef. How to debug that?
Also I’ve spent some time searching for entry point ( main() ), until I realised, that this project has loop()… Arduino?…

I have such interest in that question for the following reason. I’m interested in combining my Indigo with your Anduril, if it is relatively easy to accomplish. We can take familiar to people here front level of interface, and place it on top of good system algorithms, that allow to create good linear regulator on the same FET. It will be even cheaper and more compact than existing solutions on AMC7135+FET. Writing interface on assembler is perversion, but necessity, because it is not clear, how to implement system part on C. And that slows project down, because everyone is afraid to use assembler. And I can’t always support that all, can I? We’ve got “Maidans” here, so it’s hard to find time sometimes.

I don’t mind having lots of good flashlights in the world. But I can’t produce them all by myself (for mass production), and companies don’t like open source projects :slight_smile: . But here is such a unique situation with these Narsil/Anduril – maybe it’s possible to help project in some way and at the same time push forward my own ideas.

In every Indigo I did the same (but with assembler). I wouldn’t say that thing is easy and clear. It’s tedious and worse than piecing a puzzle. There are a lot of recursions and lots of paths had to be kept in mind, if one want to get convenient interface, that can get you anywhere along with context. For me that is the most unpleasant part of work.

I write on C and assembler. And for AVR I see no possibility to use C for mentioned things, that are, on the other hand, can be easily written in assembler. With ARM problem isn’t that critical, but these MCU are worth using only in especially huge projects.

Without inline assembler this thing requires unacceptable amount of resources. There are many channels (Unicorn has 3), and they work on frequencies of tens and hundreds kHz. If you will manage to implement something like this on C, that would be interesting.

There is no wear levelling. Only wear reduction. Levelling is present in Meteor, because there are a lot of constantly changing data stored for self-calibration and at the same time a lot of free EEPROM. There are common memory for every UI and not much user data to be stored. Unicorn is another story: Every UI has independent space, store a lot of data, there aren’t much memory (128 byte), and half of it is allocated for factory settings copy (storing such things in flash is luxury). At the end, it leaves us with 16 bytes for single preset, where full configuration for particular interface should be stored. There are nothing to level wear with. Moreover, such algorithms are complex: Beside regular count of write cycles and data remap, they can find defective memory cells and put them in reserve. And use them later when there are no healthy cells left, etc. Such things require lots of memory and thorough testing, because glitches can occur many years after production, when first defective cell is detected or algorithm will stuck on last cell, continuously wearing it out. Brr…

Sorry about the #ifdefs. I have been meaning to clean out some of those. They grow like weeds, as I add hardware and software options people ask for. But much of it has become messy and needs cleaning.

It does not use Arduino. However, FSM provides an Arduino-like style for writing UI code. The actual main() is in fsm-main.c. UI code has setup() and loop() instead. This is documented in spaghetti-monster.txt.

Good system algorithms are good. :slight_smile:

Most of the work remaining in FSM is to improve the system algorithms. I have a long list of tasks waiting. Most of these make little or no visible difference to the user, but they are still an important part of the foundation.

It works on a linear FET driver. This is used in the Emisar D1S V2. There is also a version which runs on a regulated buck driver, in the BLF GT. The main reason these are not used more often is because there are not enough circuit engineers to keep up with the demand for new circuit designs.

It may be difficult to merge assembly and C, but there are ways to do it. I think perhaps one of the biggest changes is less about the language though, and more about the abstract ideas used. If I understand correctly, Indigo calculates brightness or power on a linear scale, and does math inside to convert linear brightness into a curved ramp?

That seems like a good way to do it, and has advantages like high resolution and straightforward thermal control.

I used a different method, which has some benefits and drawbacks. The perceptual brightness curve is calculated on a computer and saved to a table, so the firmware uses perceptual brightness steps instead of linear power. This makes the ramp shape easy to adjust for a wide variety of hardware, but the resolution is lower and it makes thermal regulation difficult. So that might need to change, and it is not an easy change.

Some companies are afraid of open source projects. However, many companies love open source. They get years of work for a low price. Usually it is not very difficult to explain open source software to companies in a way they understand:

  • With proprietary software: You get what you pay for.
  • With open source software: You get what you pay for. Everyone gets what you pay for. You also get what everyone else pays for.

Overall, everyone pays less and gets more.

It sounds pretty unpleasant. That is why I made FSM. With it, I was able to create clones of a few popular flashlight interfaces in just a few hours.

The Olight Baton clone is the simplest and easiest to read, and makes a good introduction to how to use FSM. I also made a copy of ZebraLight’s UI and called it DarkHorse, but I don’t think anyone uses it.

The next day, I started on a clone of the Meteor. UI1 and UI2 were simple to do, but I stopped halfway through UI3 when I noticed it uses short clicks and medium clicks in addition to longer hold events. FSM provides events for short clicks and longer holds, but nothing for a medium click. So I stopped for the day and then never got back to it.

With UI1, UI2, and half of UI3, it compiles to 3818 bytes. So it currently fits on attiny45, but a finished version would probably need attiny85.

I think I found a gcc option to bind registers, or restrict which registers it can use. Maybe that helps?

I implemented a 4th PWM channel in C, using a PWM timer interrupt to turn an extra pin on and off. It works, but sometimes it flickers when two interrupts happen at the same time. So I hope to greatly reduce the time used by each interrupt, to improve timing consistency.

To implement DSM seems much the same, except instead of turning a pin on or off, it would change the duty cycle for built-in hardware PWM. It seems like it should work, but I haven’t tried it yet.

Ah, okay. I have not attempted to detect and track dead cells. Without that though, wear levelling is pretty easy and does not require much code.

Wear levelling is probably not needed though, since these eeproms last a long time. I did not bother using wear levelling for config values. It is used only on the dual-switch version. With a tail clicky switch, power is disconnected frequently so I used wear-levelled eeprom to store the memorized brightness level.


Anyway, long message! It is good to talk to someone who understands these things. I hope we are not boring everyone.

That’s easy:

register uint8_t output asm("r3");

This shows how to assign variables to registers and how to use assembler inside of a C program. Here’s another example:

uint8_t delay_seconds;
asm volatile (
  "ldi %[i], 5"    "\n\t"
  "0:"             "\n\t"
  "rcall  delay_s" "\n\t"
  "dec    %[i]"    "\n\t"
  "brne   0b"      "\n\t"
    : [i] "=&r" (delay_seconds)
);

If you are working directly with registers, in some cases it might be wise to tell gcc not to use it via the option:

-ffixed-r**

i also posted review of Unicorn, there is bunch of examples how it performs

video has english subtitles.

Great review, saw it already a few days ago. Shows almost every aspect of the Unicorn.

Low, Mid(ish), High:

CCT = 4073K (Duv 0.0034)
Color Rendering Index (Ra) = 94.1 [ R9 = 80.6 ]

CCT = 4099K (Duv 0.0029)
Color Rendering Index (Ra) = 92.8 [ R9 = 76.9 ]

CCT = 4172K (Duv 0.0004)
Color Rendering Index (Ra) = 91.8 [ R9 = 74.2 ]

Thanks for the measurements!

Anyone out there able to get the head off of this light?
I just tried with a strap wrench … nope - Mine seems to be locked on.

http://forum.fonarevka.ru

pre-production sample in photos - maybe that’s why it wasn’t glued eh?


I just tried again, with 2 strap wrenches …. the awesome knurling is so aggressive, it destroyed the rubber strap while turning.
Head still glued … :smiling_imp:

Here are release versions: Показать сообщение отдельно - YLP Unicorn 1.0 - волшебная рабочая лошадка!
But everything unscrewed as expected.

Dang Inferion, you sure have a lot of these things!

Just to summarize this link basically says they headed up the head first and it released by hand (kind of like hot glue I guess). So it seems the key is HEAT!

That’s right, and I’ve described that earlier here: [New + Review] YLP Unicorn 1.0 (1x18650, LH351D, backlit side switch, magnetic tail, TIR lens, ramping) - #122 by Inferion

Which one of these do I use again? The shipping discount is real.

The 10 degree beaded optic is like 10% or less loss in lux with no visible rings anywhere. hot spot fades into corona which fades into spill.

The 5 degree smooth has basically the same hot spot (it’s not more throwy) as stock but changes the corona up a little, maybe slighly less rings but it’s still not smooth by TIR standards.

The 15 degree smooth turns it into a bat signal (10-15% loss in lux) but the hotspot is very wide, smooth and round with corona and spill fading to nothing quickly. (reminds me of my Carclo smooth narrow triples with LH351D)



I think I like 10 degree beaded the best of the ones I tried followed by 15 degree smooth.

Good info. Optics are on my long list of things to order.

I never got round to ordering the unicorn with the discount though so I’m waiting/hoping for that again.

Just received the light and sadly notice some dirt/finger print on the inside of the lens. Is there anyway to open it and clean?

Press the head against a sticky/rubbery surface and unscrew the bezel.

It can be unscrewed? Not press fit?

Yes it can be unscrewed.

And without OpAmp, like in Unicorn? MCU+FET and nothing else?

That’s weird. In my view, programmers are also PCB and schematic developers. These tasks can’t be addressed separately. And there are enough people to write programs.

I don’t think so. Problem is the technical feasibility of these ideas and they can be anything – this doesn’t affect the implementation of the current regulator. There are will still be the same approaches and requirements, no matter what we use for UI. Even type of driver doesn’t matter much. Linear, Impulse, with external stabiliser or software, for 50mA or 50A…

It is, for now, but I’m thinking to move to a pre-calculated tabular version. That’s faster, more flexible and convenient and takes similar amount of memory.

I now have a resolution of 160 steps, and it is enough. 160 steps is not so much for a tabular version with a depth of 16 bits (a total of 320 bytes per profile). This also does not affect the thermal control, because it takes effect after the UI with all its transformations. It modifies the Iref, that was set by UI before it arrives at the input of the current regulator. This is a system mechanism, isolated from the UI. And it does not cause any problems, so the UI can be implemented as you like …

Clones of fairly simple interfaces, which I can write in a few hours myself? Could a completed engine be so flexible and versatile to allow you to implement at least some non-standard functionality as quickly?

What I need right now:

  1. Do you have a stack of returns a step back implemented in FSM (I’m still struggling to do this with so many branches, and I haven’t gone beyond one step)?
  2. And what about predictions of further actions of the user in order to execute commands even before completion of their activation by user? With an analysis of the commands themselves, to make exceptions like “if you now need to preload the turbo, but it will be followed by the moonlight - it’s better not to preload the turbo, because a prediction error is more harmful than a good forecast”. It used to be easy to do, but now the interface has become amorphous and this mechanism should automatically change its behavior according to the situation. And without it, the interface is laggy.
  3. How does it work with context, transmitted between commands to each other (transmit brightness to a beacon, for example)? To manually drag through the variables?
  4. How easy is it to implement a configurable UI like Unicorn? Will it facilitate this task?

I’m not familiar with FSM. If it has necessary functionality for implementation of all that, than it’s interesting indeed.

It may help. If you reserve at least 16 first registers (R0-R15) for assembler inserts, the problem can be considered solved. It remains only to figure out how to explain to GCC which cells in RAM to use to communicate with assembler interrupt handlers.

And I have a 4-channel buck on ATtiny24 (located on one side of the 17mm board), and there all 4 channels work in CTC mode (250kHz, 32 steps) without any issues. Since unused Comparator C is only available on timer 1, the timer 0 is reset by interrupt of the timer 1. And thanks to ability of the assembler to strictly plan clock cycles - everything works as it should. In addition, 32 cycles are enough for the DSM of all 4 channels and there is still time left for the background loop.

And another example:
I once developed an ultrasonic positioning system for industrial machines in rooms (where GPS does not work, and its accuracy is worse, than millimetre, anyway). There the slightest jitter of the transmitter led to noticeable errors in measuring the distance to it, and again the assembler came in handy. With it, the main influence became the air flows in the room …

There are fewer latency requirements thanks to hardware synchronization of OCRXX timers over timer overflow events. But this does not cancel the requirements for code execution speed. DSM must have time to calculate everything before the end of the PWM period. And this is, well, a dozen or two clock cycles for several channels. There is no time even to save the context onto the stack…

That we’ve been translating for more than a week this time >_<…
[From translator] And this one as well. That’s on me. Sorry, I’m kinda busy and lazy. Bad mix, I know.

What do you think if I write in Russian and you will try to deal with google translate? ))