Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
LimaBiker
Dec 9, 2020




Use a bog standard PWM lamp dimmer/motor control. There are countless of those on ali/ebay. If you wanna DIY:

Adbot
ADBOT LOVES YOU

His Divine Shadow
Aug 7, 2000

I'm not a fascist. I'm a priest. Fascists dress up in black and tell people what to do.
A PWM seems really strange application for this to me? I want two hard settings only (and half voltage gives the right result) and absolutely no other fiddling with different light intensities. Has to follow a few hard rules and always work.

I guess I could set it once, then connect it so it only works in one mode, basically same way a a buck or boost converter would be used. But the worry is it will drift, being mounted in an engine compartment with all that entails.

E: Also I am working with halogen lamps
E2: The boost / buck converters are I linked to are of switched design and 90%> efficient

His Divine Shadow fucked around with this message at 08:48 on Aug 29, 2023

I would blow Dane Cook
Dec 26, 2008

I would blow Dane Cook posted:

I just killed my LED sound activated glasses kit by putting in one of the 12v batteries in the wrong way round. What components do you think I killed?



Would a schottky diode on each of the positive battery terminals be a suitable reverse battery protection?

Stack Machine
Mar 6, 2016

I can see through time!
Fun Shoe

I would blow Dane Cook posted:

Would a schottky diode on each of the positive battery terminals be a suitable reverse battery protection?

This would work in the sense that it will keep a reverse battery from frying anything downstream. It's not a popular solution because it knocks maybe 200-300mV off of the battery voltage, which may or may not be noticeable, but it's very simple compared to an ideal diode circuit.

I would blow Dane Cook
Dec 26, 2008
It's very tricky to add anything else to the board so I might give diodes a try. Alternatively these ICs were 10 for a dollar on aliexpress so maybe i could just think of them as a rather sophisticated fuse.

LimaBiker
Dec 9, 2020




His Divine Shadow posted:

A PWM seems really strange application for this to me? I want two hard settings only (and half voltage gives the right result) and absolutely no other fiddling with different light intensities. Has to follow a few hard rules and always work.

I guess I could set it once, then connect it so it only works in one mode, basically same way a a buck or boost converter would be used. But the worry is it will drift, being mounted in an engine compartment with all that entails.

E: Also I am working with halogen lamps
E2: The boost / buck converters are I linked to are of switched design and 90%> efficient
It's not strange at all. As a matter of fact, almost every dimmable light on DC uses PWM. Including LED brake lights that have 2 different brightnesses, RGB led strips, LCD backlights etc etc.
Especially for LED based stuff, a buck converter will sometimes not even work because of the threshold voltage of an LED, so PWM dimming is the only option.

Incandescent lights are the exception - those can always be dimmed by varying the voltage. But PWM works perfectly fine too.

Using a step up system and 2 different voltages of lamp in your car is madness. You only want 1 type (as in voltage) of lamp in your system.

Stepping down is sensible. Because you can use 12v standard lamps that you can buy everywhere for cheap for both bright and dim.

PWM is just another efficient way of stepping down the effective power. You set the desired brightness once and then don't touch it anymore. Put some silicone goo over it if you're worried about dust intrusion. It's not gonna drift unless you use very lovely chinese trimmers.
But you can just as well replace the potentiometer/trimmer with some fixed resistors. Use a switch to bridge one of the two resistors (or one half of the trimmer) and it should jump from the preset value to 100% duty cicle. I'm not completely in the know about actually designing PWM controllers with a 555, but i've used the circuit above countless times and it works very well.

If it so happens to be your kink, you can also use an arduino to generate a 50% (or whatever power level you want) PWM signal and switch it to 100% via a data line.

Either way, PWM is the option i'd choose because i'm used to using it. A regulator to lower the voltage will also work, though it might very well just be PWM inside without you knowing it.

LimaBiker fucked around with this message at 17:04 on Aug 29, 2023

Cojawfee
May 31, 2006
I think the US is dumb for not using Celsius
It's weird because this is for dimming lights in a car. I'm pretty sure halogen lights don't take kindly to rapidly being turned on and off. And arduinos probably don't like being in a car.

In any case, have you considered just using a beefy resistor? Considering that you don't need an exact voltage, because it's just for a light bulb, you can just throw a resistor in series when you want the bulb dimmed.

One Legged Ninja
Sep 19, 2007
Feared by shoe salesmen. Defeated by chest-high walls.
Fun Shoe

Cojawfee posted:

It's weird because this is for dimming lights in a car. I'm pretty sure halogen lights don't take kindly to rapidly being turned on and off.

My 08 Wrangler uses PWM for the halogen headlights and fog lights, and I've only ever had one of each burn out since it was new.

Edit: It's not a user accessible setting, and you'd never see it change, (at least in the US) but if you get into the CANbus you can change the values and toggle daytime running lights and whatnot.

One Legged Ninja fucked around with this message at 18:17 on Aug 29, 2023

ryanrs
Jul 12, 2011

Halogen bulbs don't mind PWM, even at frequencies as low as 120 Hz.

RabbitWizard
Oct 21, 2008

Muldoon
Edit: Disregard this post, I'm an idiot.


Hi thread :wave:
Before I burn the house down because I totally forgot something important, I thought I'd ask here. I included my napkin math/thoughts, if there aren't any serious errors everything should work just fine. My main question ist: Are the USB-charger, the balancer board and the batteries compatible? I'm sure they are, C/D?

I got a bunch of these batteries.


As there is no C value given, according to things I read on the internet, 1C should (in nearly all cases) be fine for safely charging -> 500mA current @ 3.7V
These are from single-use vape pens - what a crazy waste - and I measured 2A current while in use to power the vaporizer. Don't know if this is constantly available or just for peaks of a few seconds, doesn't matter, I'll test this before pulling serious power from them. For the USB-charger it'll be fine.

One thing that worries me is that charging current "should be" at least 0.6C. But I use one already with a tiny solar panel, solar charger and some LEDs, it functions as I expect it to and the solar panel is providing 80mW on a good day.

I have these, output 5V 1A, input 3.7V-5.5V 1A with 4.2V loading voltage, they work fine with a 3,7V 18650.
https://de.aliexpress.com/item/1005005047734813.html



If I want to use more than one of the tiny batteries, for a powerbank or something, would it be enough to buy one of these charging balancers?
https://de.aliexpress.com/item/1005005374033962.html


If I understood correctly, this will apply the charging voltage from the USB-charger to all batteries, if a battery is full it will discharge not needed power through a resistor until the other batteries caught up. Then the USB-charger should stop charging.

Charging all batteries, assuming they are totally empty (which they never should be) and the USB charger is a PoS that is only providing 1A@3.7V
1.850Wh * 8 = 14.8Wh
14.8Wh / 3.7W = 4 hours of charge time

They have a equalizing current of 66mA with 4.2V. The batteries have 1.85Wh. Worst case theoretical scenario (one totally empty battery, one 100% full) I have to balance them for
66mA * 3.7V = 244mW power passing between batteries
1850mWh / 244mW = 7.58 hours to completely fill/empty a battery
divided by 2 because each one is only (dis)charging until 50%, 7.58 / 2 = 3.8 hours
before charging.
This may be wrong if the equalizing current is shared between all batteries, but even then it shouldn't matter much while using them.

Yes, I'm aware of risks involved like short circuiting a battery, wrong polarities, batteries being below a voltage of ~2.5V, applying power where it doesn't belong, breathing soldering fumes or buying stuff from aliexpress.

RabbitWizard fucked around with this message at 20:41 on Aug 29, 2023

ryanrs
Jul 12, 2011

Explain the multi-cell pack? Because if you are planning to make an 8S pack with random, different size, disposable vape cells, that is probably a bad idea.

e: 8S would be a 33V battery pack. What is it going to be powering?

ryanrs fucked around with this message at 19:20 on Aug 29, 2023

Fragrag
Aug 3, 2007
The Worst Admin Ever bashes You in the head with his banhammer. It is smashed into the body, an unrecognizable mass! You have been struck down.
I have little to no experience with embedded electronics and I need a sanity check on my project.

I'm making a small installation with two ESP32-Cams each powering a 64x64 LED matrix panel. These would communicate with each other over wifi and allow visitors to interact with each in an indirect funky way yadda yadda.

So right now I'm prototyping and I've got an ESP32-Cam running the following process:

Capture a 96x96 image (lowest resolution) and save it to currentFrameBuffer
Compare this currentFrameBuffer with previousFrameBuffer and output a differenceBuffer with 1s where the difference between pixels are high enough and 0s where they aren't
Send this differenceBuffer to the other ESP32-Cam via TCP/IP
Overwrite previousFrameBuffer with currentFrameBuffer
GOTO 10

The performance of this is not as good as I expected, even running at the lowest resolution at roughly 6FPS. Is this to be expected and the ESP32 is just not fast enough to do this? I can always switch over to Raspberry Pis if required

RabbitWizard
Oct 21, 2008

Muldoon

ryanrs posted:

Explain the multi-cell pack? Because if you are planning to make an 8S pack with random, different size, disposable vape cells, that is probably a bad idea.

e: 8S would be a 33V battery pack. What is it going to be powering?

Jesus, I'm so dumb, they would be in series with this part :negative: I'm really not sure how I missed this. I just want the capacity. They aren't different sizes btw, each one of those is 3.7V/500mAh.

Does this mean connecting them in parallel would be enough? I may have been reading about balancing currents while you attach batteries in parallel and then somehow got the idea I need some kind of automatic balancing? Or that they may develop different capacities due to aging? I'm really not sure any more.

Glad I asked. I probably would've caught it while wiring them or looking at the diagrams longer than a second :bang:, but thanks!

ante
Apr 9, 2005

SUNSHINE AND RAINBOWS

Fragrag posted:

I have little to no experience with embedded electronics and I need a sanity check on my project.

I'm making a small installation with two ESP32-Cams each powering a 64x64 LED matrix panel. These would communicate with each other over wifi and allow visitors to interact with each in an indirect funky way yadda yadda.

So right now I'm prototyping and I've got an ESP32-Cam running the following process:

Capture a 96x96 image (lowest resolution) and save it to currentFrameBuffer
Compare this currentFrameBuffer with previousFrameBuffer and output a differenceBuffer with 1s where the difference between pixels are high enough and 0s where they aren't
Send this differenceBuffer to the other ESP32-Cam via TCP/IP
Overwrite previousFrameBuffer with currentFrameBuffer
GOTO 10

The performance of this is not as good as I expected, even running at the lowest resolution at roughly 6FPS. Is this to be expected and the ESP32 is just not fast enough to do this? I can always switch over to Raspberry Pis if required

6FPS sounds maybe in the ballpark of what I would expect with that - I found the ESP32-Cam quite slow with communicating with the sensor, and the WiFi is also quite slow.

You might be able to improve upon this.
Figure out the slowest part of your system, just with timestamps on the console or whatever. Whether that's WiFi or the sensor, or both.
If it's WiFi, consider trying to use ESP-Now instead. I found it a lot faster and more realtime. The WiFi stack on the ESP32 seems to introduce a ton of latency.
If it's the sensor, I dunno, there are a lot of hacks you could do on the image sensor component probably. It's written in a pretty general way to support like 15 different sensors, so I'm sure there are some speedups to be had.

But like, this is one of the rare cases where a RasPi Zero is actually kinda appropriate, and probably a lot less work.

ryanrs
Jul 12, 2011

For making a series pack (which is NOT what you want), you need to:
1) Sort/bin the cells by measured capacity. This will involve measuring each cell individually, then making a pack out of similar-capacity cells.
2) When charging the pack, you need a board that does cell balancing to keep them mostly matched.

For a parallel pack, the cells need to be the same chemistry, then you just wire them all in parallel. You don't need to sort the cells by capacity, and you don't need to worry about balancing. All the cells always have the same voltage because they're in parallel.

A weirdo parallel pack of mismatched cells won't share charge and discharge current equally between the cells, so don't try to push the limits. But charging 4 parallel cells, each 500mAh, with 4*0.5 = 2A is fine.


Caution: I would not charge these things unattended. Not because the parallel wiring is suspect, but because I wouldn't trust the cells themselves. And once one cell in a pack catches on fire, they all will, regardless of how they're wired.

Sagebrush
Feb 26, 2012

Cojawfee posted:

It's weird because this is for dimming lights in a car. I'm pretty sure halogen lights don't take kindly to rapidly being turned on and off.

What halogen lamps don't like is being repeatedly heated up and cooled down. If you turn the power on and off faster than the filament can respond, the average power provided to the bulb can be varied while keeping the temperature stable.

Consider that a halogen bulb plugged into 60hz AC is technically being turned "off" 120 times a second, but it works fine. As long as your PWM is a few hundred Hz or more there will be no problems.

ryanrs
Jul 12, 2011

Also the halogen chemistry doesn't work if the bulbs aren't running at rated temp, so the bulb lifetime may be lower and tungsten might be deposited on the bulb walls, causing further dimming. Wikipedia: halogen lamp has more info.

You probably don't need to care about this.

Bad Munki
Nov 4, 2008

We're all mad here.


Y'know, somehow, I actually got almost to the point of ordering myself a shiny new custom PCB, and I just realized I never checked one specific and crucial thing, which may have ended in sadness by frying some expensive component.

So here's the LED driver that I'm trying to control from a raspi zero:



I can't find any sort of data sheet for it, but the company's product catalog is available here: http://www.becky-usa.com/WebUpload/UpLoadFile/202352242826677.pdf

Within that, I can't find the exact model number. Close in a few places, and in one section they have what appears to be a build-your-own-model-code section. That's the only one that has a BQE96 prefix, so I suspect that's most likely the right product family, with CYOA specifics:



In the features section for that product family (and all the others that offer dimming), it states,

quote:

Optional for 0-10V/PWM/resistance dimming
If you look at the product pic above, it just has purple/gray DIM+/DIM-, although I did just now see the "Control Mode: 0-10V"

At this point, I'm thinking I definitely have an incorrect selection for my digital potentiometer. The part I currently have on hand is a little I2C quad pot, it'll run on like 2.5-5.5V. The Pi operates at 3.3, and the data sheet for the pot specifically states that the PA/PW/PB pins should be at an absolute max of VDD + 0.3V. As I see it, the easiest way to interface this thing with the Pi is to run it at 3.3V and just keep everything at the same logic level. Alternately, a 3.3-5V logic level converter if I wanted to run it at 5V for whatever reason. But the little thing still wouldn't be able to manage what I expect is 10V on DIM+.

I figure I should probably get an ohmmeter on those two leads, I think I should expect to see 10V across them? If that's the case, anyone have suggestions for a digital pot (preferably 3.3V I2C) that can handle 10V on its PA/W/B pins? Or some other solution? Adding more components is fine, I have plenty of space.

I'm also not sure what to make of the "0-10V/PWM/resistance" phrasing. Maybe it's all the same, just that it's looking at the voltage on DIM- and it's filtered enough that both dropping it via resistance or via PWM will work. I'm out of direct PWM pins on the Pi though, I was planning to use those for fans.

Mostly just happy I didn't fry the Pi's I2C bus by slamming 5V into it, and that I didn't waste time ordering a faulty PCB.

ryanrs
Jul 12, 2011

A "0-10V dimmer" is a specific 2-wire device that connects to those 2 dim wires on your power supply.

I'm not so sure a pot is what this thing does. It might be a something more like a variable voltage clamp. Hopefully another poster is more familiar with them. It would be designed in such a way that you could use one knob to control multiple power supplies, I think.

Bad Munki
Nov 4, 2008

We're all mad here.


Well, the control that came with it was just a 100k rotary pot on those two wires. I had previously replaced it with a 100k linear pot which worked great. Just trying to go digital now.

ryanrs
Jul 12, 2011

Oh, yeah then it should work with just a pot.

Digipot 100k 36V but might need split supplies, ugh.

something something op-amp

e: LT1783 may be useful

ryanrs fucked around with this message at 04:46 on Aug 30, 2023

His Divine Shadow
Aug 7, 2000

I'm not a fascist. I'm a priest. Fascists dress up in black and tell people what to do.
e: nevermind, feel this discussion ran it's course.

His Divine Shadow fucked around with this message at 05:18 on Aug 30, 2023

ante
Apr 9, 2005

SUNSHINE AND RAINBOWS

Bad Munki posted:

Y'know, somehow, I actually got almost to the point of ordering myself a shiny new custom PCB, and I just realized I never checked one specific and crucial thing, which may have ended in sadness by frying some expensive component.

So here's the LED driver that I'm trying to control from a raspi zero:



I can't find any sort of data sheet for it, but the company's product catalog is available here: http://www.becky-usa.com/WebUpload/UpLoadFile/202352242826677.pdf

Within that, I can't find the exact model number. Close in a few places, and in one section they have what appears to be a build-your-own-model-code section. That's the only one that has a BQE96 prefix, so I suspect that's most likely the right product family, with CYOA specifics:



In the features section for that product family (and all the others that offer dimming), it states,

If you look at the product pic above, it just has purple/gray DIM+/DIM-, although I did just now see the "Control Mode: 0-10V"

At this point, I'm thinking I definitely have an incorrect selection for my digital potentiometer. The part I currently have on hand is a little I2C quad pot, it'll run on like 2.5-5.5V. The Pi operates at 3.3, and the data sheet for the pot specifically states that the PA/PW/PB pins should be at an absolute max of VDD + 0.3V. As I see it, the easiest way to interface this thing with the Pi is to run it at 3.3V and just keep everything at the same logic level. Alternately, a 3.3-5V logic level converter if I wanted to run it at 5V for whatever reason. But the little thing still wouldn't be able to manage what I expect is 10V on DIM+.

I figure I should probably get an ohmmeter on those two leads, I think I should expect to see 10V across them? If that's the case, anyone have suggestions for a digital pot (preferably 3.3V I2C) that can handle 10V on its PA/W/B pins? Or some other solution? Adding more components is fine, I have plenty of space.

I'm also not sure what to make of the "0-10V/PWM/resistance" phrasing. Maybe it's all the same, just that it's looking at the voltage on DIM- and it's filtered enough that both dropping it via resistance or via PWM will work. I'm out of direct PWM pins on the Pi though, I was planning to use those for fans.

Mostly just happy I didn't fry the Pi's I2C bus by slamming 5V into it, and that I didn't waste time ordering a faulty PCB.

Here's a Meanwell datasheet, chosen at random. It'll likely be the same control scheme.
https://led.meanwell.com/webapp/product/search.aspx?prod=LPF-16D

ryanrs
Jul 12, 2011

ante posted:

Here's a Meanwell datasheet, chosen at random. It'll likely be the same control scheme.
https://led.meanwell.com/webapp/product/search.aspx?prod=LPF-16D

Of those options, I'd put an cheap, transistor-output optoisolator like a 4N28 across the DIM pins and PWM it with a microcontroller.

Least cost, least complexity, most likely to just work the first time.

Fragrag
Aug 3, 2007
The Worst Admin Ever bashes You in the head with his banhammer. It is smashed into the body, an unrecognizable mass! You have been struck down.

ante posted:

6FPS sounds maybe in the ballpark of what I would expect with that - I found the ESP32-Cam quite slow with communicating with the sensor, and the WiFi is also quite slow.

You might be able to improve upon this.
Figure out the slowest part of your system, just with timestamps on the console or whatever. Whether that's WiFi or the sensor, or both.
If it's WiFi, consider trying to use ESP-Now instead. I found it a lot faster and more realtime. The WiFi stack on the ESP32 seems to introduce a ton of latency.
If it's the sensor, I dunno, there are a lot of hacks you could do on the image sensor component probably. It's written in a pretty general way to support like 15 different sensors, so I'm sure there are some speedups to be had.

But like, this is one of the rare cases where a RasPi Zero is actually kinda appropriate, and probably a lot less work.

Thanks, I guess I underestimated how much processing power it would take to calculate that. Once WiFi got involved that dropped even more though I think that was more due to my shoddy implementation.

I'll switch over to an SBC then. Hopefully I can find another use for these ESP32-Cams later

Foxfire_
Nov 8, 2010

The math you are doing on the images is piddly and should be fast (96x96~=10kb).

The speed that you can read from your camera and the latency of your tcp/ip stack will be ???. I wouldn't really expect raw cpu speed to be bottlenecking, more the design of those components and the software interfacing to them

Fragrag
Aug 3, 2007
The Worst Admin Ever bashes You in the head with his banhammer. It is smashed into the body, an unrecognizable mass! You have been struck down.
This is the code I'm running on it (sans TCP packet sending). Maybe the buffers being written in PSRAM might be the bottleneck. I had a larger framesize earlier which is why I put it in PSRAM...

C++ code:
// CAMERA
// Frame size is 96*96 or 9216 or 9.216kb
camera_fb_t* fb;
const int frameSize = 9216;
const int differenceThreshold = 128;

uint8_t* prevFrameBuffer;
uint8_t* differenceBuffer;

void setup() {
  Serial.begin(115200);
  Serial.setDebugOutput(true);
  Serial.println();

  // Allocating framebuffers to PSRAM
  prevFrameBuffer = (uint8_t*) ps_malloc (frameSize * sizeof (uint8_t));
  differenceBuffer = (uint8_t*) ps_malloc (frameSize * sizeof (uint8_t));

  // Starting camera
  init_camera();
}

void loop() {  
  fb = esp_camera_fb_get();
  if(!fb){
    Serial.println("Camera capture failed");
    return;
  }
  else {
    setDifferenceBuffer(fb);
  }
  esp_camera_fb_return(fb);
}

void setDifferenceBuffer(camera_fb_t* frameBuffer) {
  // First we check if prevFrameBuffer is valid. 
  // This if statement should only trigger starting the second pass
  if(prevFrameBuffer) { 
    // Serial.println("Difference frame buffer updated");
    for (int i = 0; i < frameSize; i++) {
      uint8_t difference = abs(frameBuffer->buf[i] - prevFrameBuffer[i]);
      differenceBuffer[i] = (difference > differenceThreshold) ? 1 : 0;
    }
  }

  // Then, if the length is the same, copy from the frameBuffer to prevFrameBuffer
  // One issue might be if the length is not identical
  if (frameBuffer->len == frameSize) {
    // Serial.println("Previous frame buffer updated");
    memcpy(prevFrameBuffer, frameBuffer->buf, fb->len);
  }
}
EDIT: Ok that doubled the FPS

ante
Apr 9, 2005

SUNSHINE AND RAINBOWS
Probably also stopped the flash LED from randomly lighting up too, that's an annoying design decision

FatCow
Apr 22, 2002
I MAP THE FUCK OUT OF PEOPLE
I've mocked the individual circuits up on the breadboard, printed it out to scale to test fit things. And other than the fuses being in fairly un-ideal locations for replacement I think I'm happy. Is there anything glaringly obvious that seems wrong before I send this off to be produced?



There is clearance under the 2 sub-boards for the screws. I made the traces thicker for the power nets and the +24v that passes through to the AC contactor. They are .5mm


The fill on the back is ground, the other 2 traces are +5v and +3.3v. The fill was fixed for C3. I moved it down to have a bit more room to sneak a usb plug in there.

Foxfire_
Nov 8, 2010

Fragrag posted:

This is the code I'm running on it

Little thing:
C++ code:
  // First we check if prevFrameBuffer is valid. 
  // This if statement should only trigger starting the second pass
  if(prevFrameBuffer) { 
This bit isn't true. The implicit uint8_t* => bool conversion that is happening here is equivalent to prevFrameBuffer != nullptr. That will always be true since you set it in setup() and never change it

Bigger thing:
C++ code:
 uint8_t difference = abs(frameBuffer->buf[i] - prevFrameBuffer[i]);
This line probably isn't doing what you want. Your pixel values are unsigned and can't represent negative numbers. The subtraction will wrap around instead of being negative, then the abs() does nothing. For example, if frameBuffer->buf[i] was 5 and prevFrameBuffer[i] was 6, difference will be 255, not 1

Algorithm changes for speedups:
- You are handling each piece of the new frame twice per loop, once to compute the difference and once to copy it to prevFrameBuffer. That's two fetches to (slow) memory. This may or may not be being optimized away depending on how good your compiler is, but you can write the code to not have it at all
- Looking at esp32-camera source (it doesn't seem to have any API documentation I can find?), you can have up to fb_count frames outstanding at once. It has a marker on each one indicating if it's in use. When you ask for a new frame, it scans until it finds an unused one, sets up DMA from the camera into that, then waits until that finishes. So you don't need to copy into prevFrameBuffer at all. Just keep the copy you originally got for one extra acquisition, then return it

An implementation of that (that I haven't compiled, probably has syntax errors):
C++ code:
// This is assuming C++11 for `auto`, `constexpr`, and `nullptr`

//-------------------------------------------
// Constants
//
// constexpr := "This is a compile time constant"
// static := "This symbol is only for this .cpp file"
//-------------------------------------------
static const constexpr int FRAME_SIZE = 96 * 96;
static const constexpr int DIFFERENCE_THRESHOLD = 128;

//-------------------------------------------
// Global data
//
// (I like to put stuff in structs to qualify 
//  names.  This is making one instance of a struct with
//  these fields that is static [only accessible from this .cpp])
//-------------------------------------------
static struct 
{
  // Previous frame we got from the camera.  
  // null if we haven't ever gotten one
  camera_fb_t* previousFrame = nullptr;

  // FRAME_SIZE long array of 0/1 values, representing whether that pixel
  // was different enough, allocated in PSRAM
  //
  // (You could also do this without a heap via the appropriate linker
  // instruction to tell it to place a plain `uint8_t differenceBuffer[FRAME_SIZE]`,
  // or better `std::array<uint8_t, FRAME_SIZE>` (if you have C++11) in PSRAM)
  //
  // But a heap allocation is fine too.
  uint8_t* differenceBuffer = nullptr;
} globals;

//-------------------------------------------
// Set everything up
//-------------------------------------------
void setup() 
{
  Serial.begin(115200);
  Serial.setDebugOutput(true);
  Serial.println();

  // Allocate space for differences in PSRAM & zero it.  The zeroing is to make it have
  // non-trash values before we have two good camera frames and write it normally
  globals.differenceBuffer = (uint8_t*)ps_malloc(FRAME_SIZE * sizeof(uint8_t));
  std::memset(globals.differenceBuffer, 0, FRAME_SIZE * sizeof(uint8_t));

  // Starting camera
  //
  // Make sure config->fb_cnt is >1 so we can have 2+ buffers outstanding
  init_camera();
}

//-------------------------------------------
// Every loop
//-------------------------------------------
void loop() 
{
  // Acquire a new frame
  camera_fb_t* newFrame = esp_camera_fb_get();
  if (newFrame == nullptr)
  {
    // esp32-camera returns nullptr when camera access times out.
    // Or if there were no more buffers left, but that shouldn't happen
    Serial.println("Camera capture failed");
    return;
  }

  // If we don't have a previous frame, there's no differences to compute.
  // This frame becomes our previous frame and we're done
  if (globals.previousFrame == nullptr)
  {
    globals.previousFrame = newFrame;
    return;
  }

  // Compute the difference
  for (auto pxNum = 0; pxNum < FRAME_SIZE; ++pxNum)
  {
    // Doing this in wider signed math probably isn't any slower than doing it 
    // with conditionals
    const auto newPx = (int)newFrame[pxNum];
    const auto oldPx = (int)globals.previousFrame[pxNum];
    const auto delta = newPx - oldPx;
    const auto absDelta = std::abs(delta);
    globals.differenceBuffer[pxNum] = (uint8_t)((absDelta > DIFFERENCE_THRESHOLD) ? 1u : 0u)
  }

  // Old frame -> return to camera
  // New frame -> old frame
  //
  // We're only shuffling pointers around, not copying array content
  esp_camera_fb_return(globals.previousFrame);
  globals.previousFrame = newFrame;

  DoSomethingWithTheDifferencesPresumably();
}
e: packing the differences array to be 1 bit per pixel instead of 1 byte per pixel may also be faster depending on how slow psram access is. It would also reduce the amount of data to transmit

Foxfire_ fucked around with this message at 07:30 on Aug 31, 2023

Fragrag
Aug 3, 2007
The Worst Admin Ever bashes You in the head with his banhammer. It is smashed into the body, an unrecognizable mass! You have been struck down.

Foxfire_ posted:

A poo poo ton of helpful stuff

Thank you very much! You're a legend. This lower-level approach to programming is still very new to me so this is really helpful. Especially the comments on constexpr and static

quote:

This line probably isn't doing what you want. Your pixel values are unsigned and can't represent negative numbers. The subtraction will wrap around instead of being negative, then the abs() does nothing. For example, if frameBuffer->buf[i] was 5 and prevFrameBuffer[i] was 6, difference will be 255, not 1
Oh that's an obvious rookie mistake, thanks for pointing that out

quote:

Looking at esp32-camera source (it doesn't seem to have any API documentation I can find?), you can have up to fb_count frames outstanding at once. It has a marker on each one indicating if it's in use. When you ask for a new frame, it scans until it finds an unused one, sets up DMA from the camera into that, then waits until that finishes. So you don't need to copy into prevFrameBuffer at all. Just keep the copy you originally got for one extra acquisition, then return it
The API documentation is in the library header itself, which isn't completely perfect. One thing that's not clear to me yet is where the framebuffer is stored? Is it in the SRAM, PSRAM or somewhere else? The OV2640 camera module max resolution is 1600x1200, which is still too large for the SRAM even at 1BPP

quote:

e: packing the differences array to be 1 bit per pixel instead of 1 byte per pixel may also be faster depending on how slow psram access is. It would also reduce the amount of data to transmit
I was thinking of that too. That'll be a interesting introduction into bitwise operations.

Another thing I overlooked as well is the camera's exposure settings themselves. If it has a long exposure time, that'll probably affect the (perceived) framerate as well of course

Dominoes
Sep 20, 2007

ante posted:

Autodesk / Fusion buying up Eagle, an established piece of software, and integrating it makes a ton of sense. The idea of building out a board and an enclosure in one package is great, and I'd love for it to make sense.

But you know, gently caress autodesk and KiCad rules

So wise

PRADA SLUT
Mar 14, 2006

Inexperienced,
heartless,
but even so
autodesk pcb sucks rear end

deoju
Jul 11, 2004

All the pieces matter.
Nap Ghost
Can somebody help me out? What are these things called? I don't know the right term to google them.


I'm building a Aura Video Analyzer Helmet since I've already got a Portable Positron Collider

ante
Apr 9, 2005

SUNSHINE AND RAINBOWS
Ring terminals on the right, and then the ones on the left are an ecosystem of spade and fork terminals

Cojawfee
May 31, 2006
I think the US is dumb for not using Celsius
The ones on the left are the receiving end of a spade connector. The other ones I think are ring terminals.

mewse
May 2, 2006

I think collectively they're referred to as crimp terminals

deoju
Jul 11, 2004

All the pieces matter.
Nap Ghost
Thanks.

If any of you get attacked by a terror dog, or have an ancient Mesopotamian diety in your fridge hmu. :ghost:

taqueso
Mar 8, 2004


:911:
:wookie: :thermidor: :wookie:
:dehumanize:

:pirate::hf::tinfoil:

PRADA SLUT posted:

autodesk pcb sucks rear end

reminded me of solidworks pcb, which I've seen in the installer but never used. I assume it is terrible, anyone actually tried it?

Adbot
ADBOT LOVES YOU

Bad Munki
Nov 4, 2008

We're all mad here.


ryanrs posted:

Of those options, I'd put an cheap, transistor-output optoisolator like a 4N28 across the DIM pins and PWM it with a microcontroller.

Least cost, least complexity, most likely to just work the first time.

That made sense enough to me, so I took a stab at it. Different part, I went for a 4-channel surface mount option since I need all four. Along with that, I'll need four extra PWM channels to drive it. There are libraries out there to do that in software on the Pi, but that's going to top out at a much lower frequency, and is targeted more towards motor control. So, I stuck a 4-channel I2C LED driver in the mix. Maybe that's not the right answer? Like the part I picked is probably overkill? But something like that. Someone can let me know if there's a better selection for that part.

Anyhow, my schematic is as per the typical application sample in the data sheet for the driver.


L5, L6, L7, L8 will be handling 10V, I believe. The rest is all 3V3.

I2C LED Driver: https://www.digikey.com/en/products/detail/lumissil-microsystems/IS31FL3197-QFLS2-TR/14308398

Optoisolator: https://www.digikey.com/en/products/detail/liteon/LTV-847S/385841

If this all looks right, I'm happy with it. It's two small chips instead of 1, no big deal. A handful of extra caps and resistors. I have plenty of space to work with on my board.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply