Matchboxscope / matchboxscope.github.io

Online Tool to upload Matchboxscope/Anglerfish firmware
https://matchboxscope.github.io/
MIT License
2 stars 2 forks source link

Getting Spectrometer Software running on/for the ESP? #1

Open beniroquai opened 1 year ago

beniroquai commented 1 year ago

Hey @Ethanjli, guess what, I had yet another idea what to do to make the esp even more complete. The ESPectrometer. The hardware looks like this: image

and acquires images like that

image

I found a very neat javascript implementaiton of analysing the data in the browser here: https://github.com/GaudiLabs/3DFiberSpectrograph

And attempted to think of: how could I make use of it with the MJPEG stream coming from the ESP32 camera. I got it working locally by adding CORS headers to the matchbox firmware. The ultimative goal would now be to have the website hosted e.g. on github-pages and access the stream somehow. Do you think this is somehow possible? I naively entered the local IP address of the ESP in the index.html: https://github.com/Matchboxscope/matchboxscope.github.io/blob/main/spectrometer/index.html#L64 which obviously is stupid (?). I was wondering if there is any simple way to achieve this (e.g. access the mjpeg stream from the ESP32 in the same network to display that in the html-website loaded from github-pages. Does this make sense to you?

beniroquai commented 1 year ago

The spectrometer page can be found here:

https://matchboxscope.github.io/spectrometer/index.html

and looks like this:

image

The original implementation makes use of the getUserMedia() function that accesses the (USB)-webcam

ethanjli commented 1 year ago

The ultimative goal would now be to have the website hosted e.g. on github-pages and access the stream somehow. Do you think this is somehow possible? I naively entered the local IP address of the ESP in the index.html: https://github.com/Matchboxscope/matchboxscope.github.io/blob/main/spectrometer/index.html#L64 which obviously is stupid (?). I was wondering if there is any simple way to achieve this (e.g. access the mjpeg stream from the ESP32 in the same network to display that in the html-website loaded from github-pages. Does this make sense to you?

Ooooh, that's an interesting question. Basically you're asking for a simple way to have 1) a JavaScript library running in the browser which 2) can discover other devices on the LAN and establish a direct peer-to-peer HTTP connection to an ESP32 device on the LAN, and it sounds like you're also asking to do this 3) without running any other network server application (e.g. a web server or a network relay or a server to introduce devices to each other). I'm 80% sure that you cannot simultaneously meet all three of these requirements; it's possible to meet 2 and 3, or maybe 1 and 2.

One option could be to set up mDNS and the correct CORS configuration. This is how the PlanktoScope normally works over its own self-hosted wifi network or a LAN. If you absolutely require that the MJPEG stream must be transported directly over the LAN without being relayed through the internet, this is going to be your best option. However, I'm not sure whether/how it's possible to make mDNS work from the ESP32, and you might be limited to only one device per LAN (or else you'll need to be clever about how you use mDNS). Another caveat is that on any Windows device you'll need to download an mDNS client (e.g. Apple's Bonjour software); and I've personally had issues on Android, though mDNS should be supported on Android. There is nontrivial complexity involved in troubleshooting issues with mDNS if it doesn't immediately work on your computer.

If you can sacrifice making it work in the web browser and you absolutely do not want to run any network server programs, then we're looking at (what I would consider "bleeding edge") p2p technologies like https://docs.holepunch.to/building-blocks/hyperswarm . However, I doubt that it would be feasible to use any of these technologies directly on the ESP32 - you'd instead have to run some intermediary software on a Raspberry Pi or some other computer, like what we've discussed in the context of Matchboxscope and ZeroTier. Not very simple.

If you must have it work in the web browser, and you require that the MJPEG streams be transported over the LAN without being relayed through the cloud, and you're willing to run your own MQTT broker server or web server (or rely on some kind of hosted service), you can have ESP32 devices announce/publish their own device names and local IP addresses on their LANs to the server, and then in the web browser you can use JavaScript to look for that device's IP address through the server and establish a normal HTTP connection to it. This is relatively simple.

Similarly, you could use the experimental and unofficial Web Bluetooth browser API to scan for local BLE devices, which can use Bluetooth to advertise theirnLAN IP addresses. This might not work in Firefox or Safari, though. I'm not sure how much software complexity BLE would add to your project, though I consider uneven browser support and the experimental status of the technology to be a high "complexity factor".

If you must have it work in the web browser and you are willing to relay the MJPEG stream through the cloud (rather than transporting it directly over the LAN), the software architecture can be relatively simple - i.e. basically what my pslive software is doing. But I'm backlogged on the functionality for making it possible to publish a stream to pslive without using ZeroTier. If your required functionality is time-sensitive enough that you're willing to prototype your own implementatjon, there are probably existing software libraries that you could combine to send images over websockets to a server, and then have the server publish those images in an Mjpeg stream (or just send the images over websockets directly to the web browser, without doing anything in the MJPEG-over-HTTP transport format); this would be pretty simple.

beniroquai commented 1 year ago

Wow! @ethanjli this is an insanely valuable resource! Thanks!! :-) My take home message is now, that it's not possible - but there are alternative pathways! That's good. In best case I don't want to rely on external routing e.g. cloud servers. So perhaps a safe bet would be something you've mentioned partially => pack the MJPEG stream into USB serial and decode that in javscript locally? It could work with reasonable framerates. If you go for insane high baudrates. Then we only need to decode the serial into BASE64 data and display/process it.

Sounds completely undoable for me,..but I always wanted to learn javascript :D https://www.youtube.com/watch?v=zk0xY88l6Rc&ab_channel=ThatProject

and then the Web-serial interface I implemented here https://youseetoo.github.io/indexWebSerialTest.html

In case we would know the IP Adress of the ESP32 in the local network - would it then be possible to readout the mjpeg stream from the static website?

beniroquai commented 1 year ago

Update - wrong link to youtube: https://www.youtube.com/watch?v=-jygTxRmroA&ab_channel=ThatProject

And then Source code: https://github.com/0015/ThatProject/tree/master/ESP32CAM_Projects/WIRED_ESP32_CAM_with_FlutterApp

beniroquai commented 1 year ago

Works in principle - at least from the receiving side:

image

This is the Base64 stream from the esp32 camera over serial in the browser. Now #somebody would need to convert that into a jpeg inside an image tag ;-)

ethanjli commented 1 year ago

In case we would know the IP Adress of the ESP32 in the local network - would it then be possible to readout the mjpeg stream from the static website?

Yes, you'd just have the static website embed an iframe which loads and displays the MJPEG stream from the ESP32's IP address. You can only guarantee a static IP address for the ESP32 on a wifi network created and managed by the ESP32; otherwise it's almost always getting a dynamic IP address (i.e. assigned by your router). mDNS is intended to make it possible to discover the IP addresses of devices from local domain names (e.g. matchboxscope-498329.local), even if they're dynamic IP addresses rather than static IP addresses.

So perhaps a safe bet would be something you've mentioned partially => pack the MJPEG stream into USB serial and decode that in javscript locally?

Great idea, actually! This should definitely work - essentially you're using your ESP32 as a USB webcam. Here's a function I had written for my project which displays an image (inputted as a base64-encoded string) in a canvas HTML element:

async showFrame(canvas, data) {
    // Make an image bitmap from the data
    const decoded = atob(data);
    const array = new Uint8Array(decoded.length);
    for (var i = 0; i < decoded.length; i++) {
      array[i] = decoded.charCodeAt(i);
    }
    const bitmap = await createImageBitmap(
      new Blob([array], { type: 'image/jpeg' }),
    );
    // Show the image in a canvas
    canvas.width = bitmap.width;
    canvas.height = bitmap.height;
    canvas.getContext('2d').drawImage(bitmap, 0, 0);
  }
beniroquai commented 1 year ago

Awesome. I'll try my best to get it working. Perhaps USB is even more reliable than wifi.. I tried this https://stackoverflow.com/questions/21227078/convert-base64-to-image-in-javascript-jquery But now my USB micro broke and I'm travelling...nooo :D

Felt way too easy. Will report back when I'm wired up again! :)

beniroquai commented 1 year ago

Thanks a lot @ethanjli

beniroquai commented 1 year ago

Your code looks much more mature. I'll give it a try!:)

On Thu, Feb 23, 2023, 17:41 Ethan Li @.***> wrote:

In case we would know the IP Adress of the ESP32 in the local network - would it then be possible to readout the mjpeg stream from the static website?

Yes, you'd just have the static website embed an iframe which loads and displays the MJPEG stream from the ESP32's IP address. You can only guarantee a static IP address for the ESP32 on a wifi network created and managed by the ESP32; otherwise it's almost always getting a dynamic IP address (i.e. assigned by your router). mDNS is intended to make it possible to discover the IP addresses of devices from local domain names (e.g. matchboxscope-498329.local), even if they're dynamic IP addresses rather than static IP addresses.

So perhaps a safe bet would be something you've mentioned partially => pack the MJPEG stream into USB serial and decode that in javscript locally?

Great idea, actually! Here's a function I had written for my project which displays an image (inputted as a base64-encoded string) in a canvas HTML element:

async dispatchMessageEvent(canvas, data) { // Make an image bitmap from the data const decoded = atob(data); const array = new Uint8Array(decoded.length); for (var i = 0; i < decoded.length; i++) { array[i] = decoded.charCodeAt(i); } const bitmap = await createImageBitmap( new Blob([array], { type: 'image/jpeg' }), ); // Show the image in a canvas canvas.width = bitmap.width; canvas.height = bitmap.height; canvas.getContext('2d').drawImage(bitmap, 0, 0); }

— Reply to this email directly, view it on GitHub https://github.com/Matchboxscope/matchboxscope.github.io/issues/1#issuecomment-1442091126, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABBE5OHM7XU3PBFUCQHFAFTWY6HKJANCNFSM6AAAAAAVBGBITI . You are receiving this because you authored the thread.Message ID: @.***>

ethanjli commented 1 year ago

Awesome. I'll try my best to get it working. Perhaps USB is even more reliable than wifi..

If you can use USB instead of wifi, that'll be much simpler (technologically) and easier to work with!

I tried this https://stackoverflow.com/questions/21227078/convert-base64-to-image-in-javascript-jquery

This is also a valid way to do it, though the performance might not be as good as using the canvas HTML element's JavaScript API. For your use case, the difference probably doesn't matter :)

beniroquai commented 1 year ago

It seems to be working -sometimes.

I tried your code snippet, but it gives errors about not being able to decode it. I constantly send the same base64 encoded image

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

using this code:

#define BAUD_RATE 2000000

void setup()
{
  Serial.begin(BAUD_RATE);
}

void loop() {
    digitalWrite(4, HIGH);
  String mImage = "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";
    Serial.write(mImage.c_str(), mImage.length());
    Serial.println("++++++++++++++++++++");
    digitalWrite(4, LOW);
    delay(100);
}

It gets correctly decoded e.g. here: https://base64.guru/converter/decode/image/jpg

Any guesses what I'm doing wrong? The string is correctly received (not in all of the cases though).

ethanjli commented 1 year ago

Can you also paste all of the JavaScript code you're using? It will be easier to troubleshoot with that.

One thing I'm suspicious of from seeing your Arduino code is the "++++++++++++++++++++" you're adding between each image - note that "+" characters are meant to be decoded as part of base64 decoding. I think it would be better just to use a line break ("\n") as the delimiter between images.

beniroquai commented 1 year ago

Indeed, I'll switch back to the linebreak. But it should work anyway.

The error is:

script.js:189 Uncaught (in promise) DOMException: The source image could not be decoded.

and some additional information about bytes and stuff:

image
beniroquai commented 1 year ago

Now the string that is inside data is the following:

data='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'

which is valid: image

tested here https://base64.guru/converter/decode/image/jpg

beniroquai commented 1 year ago

wohooo. it works! :D Bildschirmaufnahme 2023-02-24 um 21 02 02

This is super cool! :)

@Vsaggiomo - perhaps a solution against the stripes since we don't use the wifimodule anymore!

beniroquai commented 1 year ago

Yay! It works!

image
beniroquai commented 1 year ago

Should work once github pages updates :) https://github.com/Matchboxscope/matchboxscope.github.io/tree/main/spectrometer

beniroquai commented 1 year ago

Once I have the esp32-cam with me I'll check if the framerate and everything is sufficient.

@ethanjli would you be interested to polish the code? : D

It's a mess - but basically everything works now :)

@vsaggiamo: #gamechanger :D

image

Last bit would be to wire the firmware to the firmware-upload page :)

ethanjli commented 1 year ago

I can do some refactoring of any files you point me to.

But can you catch me up on what was the root cause of the problem you had reported, and what was the solution? Right now my understanding of the situation is roughly at the level of: "Benedict expected it to work but it wasn't working consistently, then he performed a magic spell, and now everything works perfectly"

beniroquai commented 1 year ago

It was definitely a magic spell..but more coming from your side I guess ;-) I was playing with the way javascript cuts the base64 snippets. The linebreak wasn't enough unfortunately as the Web-serial seems to add random line breaks here and there (not 100% sure why). I used a +++++ in the beginning and a ----- in the end to distinguish individual frames. The final conversion happens here (> of course it'S a mess ;-)

All in all it seems to be working. I have added a simple example for the serial-camera to work with the website here. However, the frames sometimes appear flipped and also the AWB varies. I'm not sure why.

A good start to refactor the code is probably to take care of the grabbing vs. processing frame section. I merged the two projects (guadilab > spectrometer, sparkfun > webserial) and am quite surprised that I got it working anyway. I don't know anything about javascript, but it seems to be a programming language :D Right now it's a pushing frames and pulling them which is not synchronised - but maybe that doesn't matter anyway.

The result so far looks like this: Bildschirmaufnahme 2023-02-25 um 17 07 08 Weird observation: The stream gets especially corrupted once the FOV changes a lot - that doesn't make any sense to me since MJPEG does not time-wise compression, right? Hm.

What do you think?

beniroquai commented 1 year ago

I think it would already help to have some error-handling => If frame is corrupted, don't process..

ethanjli commented 1 year ago

the Web-serial seems to add random line breaks here and there (not 100% sure why)

Oh, this is good to know - I've experienced similar kinds of problems on the Arduino Uno, which used a UART-to-USB ftdi chip rather than native USB (like what the Arduino Due has). If image corruption in the stream appears to behave like a non-deterministic process, then signal interference or transmission noise on the UART serial lines (e.g. between the ESP32-CAM module and the USB programmer module) is a plausible candidate for the root cause of the image corruption, and the unexpected random like breaks. If this is the root cause, I believe you might able to observe more frequent image corruption at higher Serial baud rates, and less frequent image corruption at lower baud rates - that might be a good thing to test.

Weird observation: The stream gets especially corrupted once the FOV changes a lot

One other test I'd suggest running so we can rule out the camera or the Arduino code as a contributor to these issues is to hard-code an image sequence (like an animation) into the Arduino code, and just play back the animation in a loop to see if corruption occurs during transmission of that image sequence.

beniroquai commented 1 year ago

Hellö @ethanjli, finally I have managed to get the 10-images-in-a-row experiment running. Looks good. But it's also smaller resolution,

Bildschirmaufnahme 2023-03-01 um 06 57 46

The testing files can be found here: https://github.com/Matchboxscope/matchboxscope.github.io/tree/main/spectrometer/ESPSendImageSeriesSerialTest

It looks much better than the camera though. Perhaps we can improve the pre-shaping of the camera to make it more robust? If the image flips, it feels like the camera restarts with the wrong format (the flipping is set in setup()). Any guesses? The code for the camera streaming is this here: https://github.com/Matchboxscope/matchboxscope.github.io/blob/main/spectrometer/ESPectrometerSerial2/ESPectrometerSerial2.ino

ethanjli commented 1 year ago

Hmm interesting, this makes more suspicious of the possibility of something weird going on with the camera or the camera software. Are you able to observe the same image corruption behavior regardless of whether the camera acquires images at 30 fps (or whatever is the normal frame rate) or at 1 fps? If it only appears at higher frame rates (or it appears much more at higher frame rates), then the first thing I would check is whether double-buffering of frames (as described in https://en.wikipedia.org/wiki/Multiple_buffering?wprov=sfla1) might be needed

Now I also wonder whether there might be some kind of multi-threaded race condition between the esp32 camera library (when it creates a new image buffer, or when it dumps the camera image into an existing buffer) and the image-streaming code (when it reads each buffer to send over HTTP) - this can happen if, for example, the ESP32-CAM library always writes new frames into the same buffer (the same pointer location). If your MJPEG-over-HTTP streaming code is indeed running in a separate thread from your main code, you might need to add some mutexes to synchronize the main thread (which is probably calling ESP32-CAM functions to save camera frames into buffers) with the thread for the MJPEG/HTTP streaming code.

beniroquai commented 1 year ago

In German there is this phrase "I only understand trainstation" :D (https://www.thelocal.de/20191129/german-phrase-of-the-day-ich-verstehe-nur-bahnhof) Well, as far as I understand, the camera produces frames on the ISP and the ESP reads out the buffer (?). So only when I call camera_fb_t* fb = esp_camera_fb_get(); a transfer may occur. (https://github.com/Matchboxscope/matchboxscope.github.io/blob/main/spectrometer/ESPectrometerSerial2/ESPectrometerSerial2.ino#L77) However, you may be very right with the assumption that there is some interference going on with the timing. I could try increasing the framebuffer? I took the vanilla Camera example to make sure that additional errors are not coming from my side, but perhaps I have to tweak the settings a bit. Do you have any chance to play with the code eventually?

one more observation: the 1.2.3...10 count lags frames. So also in case of hardcoded jpegs, the communication is buggy.

ethanjli commented 1 year ago

Oh oops, I forgot that in this Arduino code you're not doing anything with HTTP on the ESP32, you're only reading the image out and then printing it to serial - in that case we can rule out any multi-threaded race conditions.

I looked more carefully at the GIF you posted of the 10 images-in-a-row experiment with hardcoded jpegs, and I realized that there does indeed appear to be two brief frames which flash some sort of corrupted image - one frame is green (and has the number 6), while the other is blue (and has a garbled number). So it looks like there is actually some occasional image corruption (not just lagged frames) in this sequence? My conclusion is that probably the displayed image corruption is actually somehow coming from the transportation of the image over Serial (e.g. just regular data corruption over the UART), rather than anything related to the camera.

I notice that you're using a baud rate of 2000000, which I believe increases the rate of electromagnetic interference-based data corruption over UART compared to a lower baud rate like 115200. I think we need to collect more observations about the behavior of the image corruption. Can you try getting some qualitative data (e.g. animated GIFs are fine, or video recordings of your screen on the web page) on the occurrence rate and visual appearance of corrupted images at three different baud rate settings with your animated numbers test: 9600, 115200, and 2000000

Because there's probably data corruption from electromagnetic interference at any baud rate (even though it may be more severe with some settings and less severe with others), you'll need to find a way to calculate a CRC on each image frame and transmit that CRC either as part of the base64-encoded payload or just together with the base64 string in some other way. Then your JavaScript code needs to check the CRC against the image so it can detect and discard frames with corrupted data. I know there are libraries for computing various kinds of CRCs on Arduino and in Javascript, and you can either just print the CRC and the base64-string separated by a space in a single line (simpler, and still easy to parse yourself) or you can print them in a format like JSON (probably overkill).

After you implement that, I would suggest just using a newline to delimit between frames. Then you should make sure you're collecting and using every single byte between every single newline, and handling all bytes between every pair of newlines as a discrete frame - so have a buffer to accumulate all bytes collected so far in your reader.read() loop, and process and reset the buffer after each newline. Right now, with the way you're handling Web Serial read operations I suspect you might be throwing away a large number of frames because the received byte sequence was unlucky enough to be split across two or more consecutive reader.read() calls. If this is indeed happening, the animated sequence of numbers should look out-of-order, discontinuous, and/or laggy.

beniroquai commented 1 year ago

So I tried some variation in Serial Baudrate and switched over to Python for debugging:

#%%
import serial
import time
import serial.tools.list_ports
from PIL import Image
import base64
import io
import numpy as np
import matplotlib.pyplot as plt
import tifffile as tif

devices = serial.tools.list_ports.comports(include_links=False)

serialport = devices[-1].device 

# connect to Camera
serialdevice = serial.Serial(port=serialport,baudrate=1000000,timeout=1)

#%%
iError = 0
t0 = time.time()

message = ""
imageString = ""
for iimage in range(100):
  try:
      #read image and decode
      imageB64 = serialdevice.readline()
      #imageB64 = str(imageB64).split("+++++")[-1].split("----")[0]
      image = np.array(Image.open(io.BytesIO(base64.b64decode(imageB64))))

      print("framerate: "+(str(1/(time.time()-t0))))
      tif.imsave("test_stack_esp32.tif", image, append=True)
  except Exception as e:
    print(e)
    iError += 1

print(iError)

It appears that the quality remains bad, no matter what I do :D Even if I'm changing the delimiter ++++/----- to simple linebreaks, the error rate is about 50-60% and the frames that make it through are mostly corrupted: test_stack_esp32

The esp32-code is this one:

#include "esp_camera.h"

#include <base64.h>
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27

#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

#define BAUD_RATE 1000000

void setup()
{
  Serial.begin(BAUD_RATE);
  Serial.println("Start the programm");
  cameraInit();
  pinMode(4, OUTPUT);
}

void loop() {
  grabImage();
}

void cameraInit() {
  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 10000000;
  config.pixel_format = PIXFORMAT_JPEG;
  config.frame_size = FRAMESIZE_QVGA; //320x240
  config.jpeg_quality = 10;
  config.fb_count = 2;

  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    return;
  }

  sensor_t * s = esp_camera_sensor_get();
  //s->set_hmirror(s, 1);
  //s->set_vflip(s, 1);
}

void grabImage() {

  camera_fb_t* fb = esp_camera_fb_get();
  if (!fb || fb->format != PIXFORMAT_JPEG) {
  } else {

    //digitalWrite(4, HIGH);

    String encoded = base64::encode(fb->buf, fb->len);
    delay(40);
    Serial.write(encoded.c_str(), encoded.length());

  }
  //digitalWrite(4, LOW);
  esp_camera_fb_return(fb);
  delay(40);
}
beniroquai commented 1 year ago

Interestingly, that's not the case in this video (same code) https://www.youtube.com/watch?v=-jygTxRmroA&t=117s&ab_channel=ThatProject

beniroquai commented 1 year ago

So, perhaps bad luck with the CH340 USB-serial converter, voltage drops, bad USB cable or...hm.

Vsaggiomo commented 1 year ago

In that YT video, they use a TTGO camera, which is way better in terms of electronics and build, but 4x or 5x the price of the ESP32-cam. My bet is on cheap/bad electronics

beniroquai commented 1 year ago

Yeah. Good Guess. I was hoping to test the Bluetooth-Serial connection eventually, but then the camera failed to be detected. I'm sure something weird is happening on the electronics side. That's really a pity, because it would be so cool to make use of it ;-)

Message ID: <Matchboxscope/matchboxscope.github.io/issues/1/1451318061@ github.com>

beniroquai commented 1 year ago

@ethanjli It works now. I guess Mac's latest CH340 causes issues. For PySerial the same. Some timing/rising/falling edge ist odd. I have added the firmware to the https://matchboxscope.github.io/ You can check if it works by flashing the firmware and going to https://matchboxscope.github.io/spectrometer/espectrometer.html and see the spectrum :)

the proof that it works: WhatsApp Video 2023-03-05 at 13 31 33

The setup:

image