AndrisBB Posted July 17, 2022 Share Posted July 17, 2022 Tākā ārā pamatīgs karstums un neko citu interesantu darīt tāpat nav ko, tad jāieposto šodienas un vakardienas mini prototip-projekts. Problēma: Esu ievērijis ka ir pamatīgs trūkums softwārei, kas var paņemt video un uzrenderēt pa virsu kautkādus vidžetus ar sirdsdarbību, ātrumu, lokāciju utt no GPX faila. Itkā ir Garmin Virb Edit, bet tas jau pamests ntos gadus, plus softwāre ar tāda jancīga un neko nopietnu tur izdarīt tāpat nevar. Nekādus citus jēdzīgus variantus redzējis neesu. Risinājums: Uztaisīt Gstreamer pluginu, kas var nolasīt GPX failu un uzrenderēt widžetus pa virsu video. Widžeti varētu būt SVG faili ar kautkādu grafiku un tad uz katra kadra palaižas JavaScript funkcija kura saņem GPX datus, kas atbilst tam laikam, modificē SVG un atgriež pluginam, lai var uzrenderēt SVG pa virsu. Reāli pielietojums varētu būt ka vienkārši norenderē to video uz kautkāda zaļā fona, ko pēctam var izmantot jebkurā video editēšanas softā, graizīt utt. Bet var arī renderēt pa virsu jebkuram video. Arhitektūra: Lai renderētu SVG izmantoju RSVG bibliotēku no Glib. Kā JavaScript dziēju izmantoju Duktape. Ļoti minimāls dzinējs kas neko nezin par dokumentiem, tīklu utt, var izpildīt tik parastu JavaScript. Uz katru kadru Gstreamer plugins padod GPX datus, JavaScript nolasa, modificē SVG un atgriež. Tad plugins uzrenderē to SVG kadram pa virsu. Lai ierakstītu piemēram sirdsdarbību uz video un iekodētu iekš h264 var izmantot ļoti pronitīvu pipelainu. gst-launch-1.0 videotestsrc num-buffers=600 \ ! video/x-raw,width=1280,height=960 \ ! videoconvert \ ! gpxoverlay \ location=../src/gpxoverlay/assets/atom.svg \ script=../src/gpxoverlay/assets/test.js \ gpx-location=../src/gpxoverlay/assets/route.gpx \ ! videoconvert \ ! queue \ ! x264enc \ ! mp4mux \ ! filesink \ location=../video.mp4 GPX izskatās apmēram tā, kur vienkārši XML datu punkti (koordinātas padzēsu): <?xml version="1.0" encoding="UTF-8"?> <gpx creator="Garmin Connect" version="1.1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/11.xsd" xmlns:ns3="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://www.garmin.com/xmlschemas/GpxExtensions/v3"> <metadata> <link href="connect.garmin.com"> <text>Garmin Connect</text> </link> <time>2022-07-16T14:42:51.000Z</time> </metadata> <trk> <name>South Gloucestershire Cycling</name> <type>cycling</type> <trkseg> <trkpt lat="" lon=""> <ele>77.59999847412109375</ele> <time>2022-07-16T14:44:21.000Z</time> <extensions> <ns3:TrackPointExtension> <ns3:atemp>30.0</ns3:atemp> <ns3:hr>103</ns3:hr> <ns3:cad>78</ns3:cad> </ns3:TrackPointExtension> </extensions> </trkpt> <trkpt lat="" lon=""> <ele>77.8000030517578125</ele> <time>2022-07-16T14:44:22.000Z</time> <extensions> <ns3:TrackPointExtension> <ns3:atemp>30.0</ns3:atemp> <ns3:hr>103</ns3:hr> <ns3:cad>78</ns3:cad> </ns3:TrackPointExtension> </extensions> </trkpt> <trkpt lat="" lon=""> <ele>78</ele> <time>2022-07-16T14:44:24.000Z</time> <extensions> <ns3:TrackPointExtension> <ns3:atemp>30.0</ns3:atemp> <ns3:hr>102</ns3:hr> <ns3:cad>78</ns3:cad> </ns3:TrackPointExtension> </extensions> </trkpt> <trkpt lat="" lon=""> <ele>78.59999847412109375</ele> <time>2022-07-16T14:44:27.000Z</time> <extensions> <ns3:TrackPointExtension> <ns3:atemp>30.0</ns3:atemp> <ns3:hr>104</ns3:hr> <ns3:cad>78</ns3:cad> </ns3:TrackPointExtension> </extensions> </trkpt> <trkpt lat="" lon=""> <ele>79.1999969482421875</ele> <time>2022-07-16T14:44:31.000Z</time> <extensions> <ns3:TrackPointExtension> <ns3:atemp>30.0</ns3:atemp> <ns3:hr>105</ns3:hr> <ns3:cad>77</ns3:cad> </ns3:TrackPointExtension> </extensions> </trkpt> Loti vienkāršs SVG widžets (jātrod kāds mākslinkies, kas sazīmē ko interesantāku) <?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns="http://www.w3.org/2000/svg" width="312" height="120" viewBox="0 0 78 30"> <text xml:id="timestamp_id" x="2" y="29" fill="blue" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:6px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#1a00ff;fill-opacity:1;stroke-width:0.265;stroke-dasharray:none"> </text> <rect style="fill:#494949;fill-opacity:0.3;stroke:none;" width="78" height="30"/> <text xml:id="label_id" x="20" y="8" fill="blue" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:6px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.265;stroke-dasharray:none"> HEART RATE </text> <text xml:id="hr_id" x="20" y="20" fill="blue" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:10px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#1ad93e;fill-opacity:1;stroke-width:0.265;stroke-dasharray:none"> 140 BPM </text> <path xml:id="heart_id" transform="scale(1.2 1.2)" d="m 14,4 a 4.0366464,4.1745268 0.0194517 0 0 -2.745618,-1.114394 4.0366464,4.1745268 0.0194517 0 0 -2.907338,1.281633 l -0.0016,-0.0017 -0.0016,0.0017 a 4.0366464,4.1745268 0.0194517 0 0 -2.907286,-1.28159 4.0366464,4.1745268 0.0194517 0 0 -4.036694,4.174578 4.0366464,4.1745268 0.0194517 0 0 1.239257,3.00659 l -0.0016,0.002 5.707812,5.90276 5.708275,-5.90325 -3.96e-4,-3.8e-4 a 4.0366464,4.1745268 0.0194517 0 0 1.23801,-3.00797 4.0366464,4.1745268 0.0194517 0 0 -1.290981,-3.060131 z" fill="#ff00ff"/> </svg> Un pats JavaScripts var document = new Document("../src/gpxoverlay/assets/atom.svg"); this.Document = document; var counter = 0; function start() { print("JS start called"); } function render(point) { counter = counter + 1; if(point != undefined) { // print(point.timestamp); var el = Document.getElementById("timestamp_id"); if(el != undefined) { el.innerHTML = point.timestamp; } el = Document.getElementById("hr_id"); if(el != undefined) { el.innerHTML = point.hr.toString() + " BPM"; } el = Document.getElementById("heart_id"); if(el != undefined) { var fill = "#ffffff" if(counter >= 0 && counter < 15) { fill = "#ff0000"; } if(counter > 30) { counter = 0; } el.setAttribute("fill", fill); } } return document.stringify(); } Gstreamera pipeline sanāk tā (kautkā baigi garais grafiks): Rezultātā video (ja forums rādīs): video.mp4 1 Link to comment Share on other sites More sharing options...
AndrisBB Posted July 17, 2022 Author Share Posted July 17, 2022 (edited) Kods te https://github.com/AndrisBB/gstreamer-gpx-overlay Pagaidām knapi turās kopā, bet strādā. Kas jādara: * Jāuzraksta labāks parsers priekš GPX failiem. Pagaidām nolasa tikai dažās vērtības, atbalsta tikai vienu segmentu un ielasa vienkārši punktus listē. Renderēšanas laikā iet cauri visai listei kamēr atrod vajadzīgo. Kautko gudrāku tur vajag. * Duktape JavaScript dzinējs ir diezgan interesants veidojums, ar kuru komunicēt nav tas vieglākais uzdevums. Jāstumda mainīgos uz no/staka. Jādomā kā kautkādā assamblerī. Domu var saprast te https://github.com/AndrisBB/gstreamer-gpx-overlay/blob/master/src/gpxoverlay/gstduktape.c Dokumentācija te. Kā izsaukt funckijas no C uz Javascript, vai no JavasScript uz C. https://duktape.org/index.html * Duktape ir pliks JavaScript dzinējs, nav tur ne Document, ne Element, nu nekā ko piedāvā browzers. Pat ne Console.log(). Nākas visu rakstīt pašam. Piemēram pagaidām no 'Document' ir viena funkcija -> getElementByID. Tāpat arī elementam ir tikai 'innerHTML' propertijs un 'setAttribute'. Izmantoju GDOMe bibliotēku SVG/HTML parsēšanai un modificēšanai. * Renderēšana pagaidām diezgan vārga. Izmantoju rSVG bibliotēku, lai uzrenderētu SVG uz kadra. Tas pagaidām knapi turas kopā. Krāsas ar var redzēt ka nav pareizās. RGBA sajaukti vietām, bet slinkums tagad risināt. * Nav nekādu widžetu. Jāpasūta kādam dizainerim iekš Fiverr.com vai kur līdzīgi, lai sazīmē ko interesantu. Īsumā - var teikt ka kautkas darbojas, bet nu tālu līdz paberigšanai, cerams nepazudīs interese un beigās kas lietderīgs sanāks. Edited July 17, 2022 by AndrisBB Link to comment Share on other sites More sharing options...
AndrisBB Posted July 17, 2022 Author Share Posted July 17, 2022 Garmin Virb Edit var uztaisīt ko tādu Link to comment Share on other sites More sharing options...
AndrisBB Posted July 24, 2022 Author Share Posted July 24, 2022 (edited) Šodien mazliet pačakarējos un uztaisiju primitīvu 'elavation' widžetu. Venkārši sākumā savāc visus punktus un tad uzrenderē pligonu un pašreizējo punktu. SVG <?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns="http://www.w3.org/2000/svg" width="480" height="240" viewBox="0 0 480 240"> <rect style="fill:#494949;fill-opacity:0.3;stroke:none;" width="480" height="240"/> <text xml:id="label_id" x="8" y="24" fill="blue" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:26px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#00ff00;fill-opacity:1;stroke-width:0.265;stroke-dasharray:none"> ELEVATION </text> <polygon xml:id="elevation_graph" points="480,120 480,240 0,240 0,48 48,96 96,72 144,100 192,144 240,100 288,84 336,73 384,65 432,55" style="fill:#6adb5c;fill-opacity:0.9" transform=""></polygon> <circle xml:id="current_pos" stroke="#000000" stroke-width="3px" cx="-10" cy="-10" fill="#ffffff" r="10" transform=""></circle> </svg> JavaScripts var document = new Document("../src/gpxoverlay/assets/elevation.svg"); this.Document = document; var counter = 0; var _segment = null; var _elevation_min = Number.MAX_VALUE; var _elevation_max = Number.MIN_VALUE; var MAX_POINTS_TO_RENDER = 480; var GRAPH_WIDTH = 480; var GRAPH_HEIGHT = 240; var _points_to_render = 0; function start(segment) { _segment = segment; // Find min and max elevation values var trkPoints = segment.trkPoints; for (var i = 0; i < trkPoints.length; i++) { if(trkPoints[i].elevation > _elevation_max) { _elevation_max = trkPoints[i].elevation; } if(trkPoints[i].elevation < _elevation_min) { _elevation_min = trkPoints[i].elevation; } } if(trkPoints.length >= MAX_POINTS_TO_RENDER) { _points_to_render = MAX_POINTS_TO_RENDER; } else { _points_to_render = trkPoints.length; } } function filter_points(points, idx) { var first_point = 0; if(idx < _points_to_render/2) { first_point = 0; } else { first_point = idx - _points_to_render/2; } return points.slice(first_point, first_point + _points_to_render); } function render(point) { var points = filter_points(_segment.trkPoints, point.idx); var polygon = "480,240 0,240"; for(var i = 0; i < points.length; i++) { var x = i * (GRAPH_WIDTH/points.length); var y = GRAPH_HEIGHT - parseInt(((_elevation_max - _elevation_min)/GRAPH_HEIGHT) * points[i].elevation); polygon = polygon.concat(" " + x + "," + y); if(point.idx == points[i].idx) { var el_pos = Document.getElementById("current_pos"); if(el_pos != undefined) { el_pos.setAttribute("cx", x); el_pos.setAttribute("cy", y); } } } var el = Document.getElementById("elevation_graph"); if(el != undefined) { el.setAttribute("points", polygon); } el = Document.getElementById("label_id"); if(el != undefined) { el.innerHTML = "ELEVATION " + point.elevation.toFixed(2).toString() + "M"; } return document.stringify(); } Edited July 24, 2022 by AndrisBB Link to comment Share on other sites More sharing options...
AndrisBB Posted July 24, 2022 Author Share Posted July 24, 2022 Divi widžeti uz parasta testa fona gst-launch-1.0 videotestsrc \ ! video/x-raw,width=1280,height=960 \ ! videoconvert \ ! gpxoverlay \ script-location=../src/gpxoverlay/assets/elevation.js \ gpx-location=../src/gpxoverlay/assets/activity_9090497773.gpx \ x=790 \ y=10 \ ! gpxoverlay \ script-location=../src/gpxoverlay/assets/test.js \ gpx-location=../src/gpxoverlay/assets/activity_9090497773.gpx \ x=10 \ y=10 \ ! videoconvert \ ! gtksink 222522974_ScreenRecording2022-07-24at16_45_36.mp4 Pa virsu video failam gst-launch-1.0 filesrc location=../rec.mp4 \ ! decodebin name=dec \ ! videoconvert \ ! gpxoverlay \ script-location=../src/gpxoverlay/assets/elevation.js \ gpx-location=../src/gpxoverlay/assets/activity_9090497773.gpx \ x=790 \ y=10 \ ! gpxoverlay \ script-location=../src/gpxoverlay/assets/test.js \ gpx-location=../src/gpxoverlay/assets/activity_9090497773.gpx \ x=10 \ y=10 \ ! videoconvert \ ! gtksink 2147137468_ScreenRecording2022-07-24at16_54_12.mp4 1 Link to comment Share on other sites More sharing options...
Dundurs Posted September 23, 2022 Share Posted September 23, 2022 Vispār priekš šādiem pasākumiem ir tāds labs softs: DashWare. Absolūti bezmaksas. Var taisīt savus widgetus, izmantot jau esošos, pielāgot tos pēc sirds patikas. Datu formātus arī atbalsta kaudzēm. Gan tādus, kas pa taisno no visādiem fitnesa pulksteņiem, gan no GoPro, utt. beidzot ar visādiem xml. Link to comment Share on other sites More sharing options...
AndrisBB Posted September 23, 2022 Author Share Posted September 23, 2022 Tas Dashware diezgan drausmīgs. Garmin Virb Edit vēl daudzmaz. Bet nu visa doma jau pārcelt visu uz pa taisno uz kameru, la i pēctam nav jātaisa post-edit. Link to comment Share on other sites More sharing options...
AndrisBB Posted September 23, 2022 Author Share Posted September 23, 2022 Domāju apskatīšu vēlreiz to DashWare, bet viņš jau tikai uz Windows darbojas. Link to comment Share on other sites More sharing options...
AndrisBB Posted October 1, 2022 Author Share Posted October 1, 2022 Šodien izdomāju mazliet padarboties. Jāpamēģina būs palaist visu pasākumu uz ARM procesora, šinī gadījumā im8m-plus. Dabūju Variscite DART-MX8M-PLUS moduli ar dev kitu https://www.variscite.com/product/system-on-module-som/cortex-a53-krait/dart-mx8m-plus-nxp-i-mx-8m-plus/ Kā arī Digilent Pcam 5c cameru ar OV5640 sensoru https://digilent.com/reference/add-ons/pcam-5c/start Kamera slēgsies pie MIPI CSI porta, tik problēma tāda ka tas devkits nāk ar tādu edge connectoru, kamēr cameras par 15 pin FPC. Uztaisiju breakout boardu, bet nu kā vienmēr sajaucu jo tas FPC connectors otrādāk, tagad pins 1 ir 15 un otrādāk, jādomā kas cits, vai jāuztaisa jauns breakout boards. Sensors kontrolējas caur I2C, to vismaz var pieslēgt ar parastiem jumper vadiem. Būs jāpamēģina to pašu izdarīt ar datu līnijām, cerams nekādi dižie traucējumi tur nebūs. Kameras sensors izskatās ka strādā, redzams iz I2C busa un var nolasīt sensora ID reģistrus. Sensora adrese 0x3C root@imx8mp-var-dart:~# i2cdetect -y 3 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- root@imx8mp-var-dart:~# i2cset -y 3 0x3c 0x30 0x0a root@imx8mp-var-dart:~# i2cget -y 3 0x3c 0x56 root@imx8mp-var-dart:~# i2cset -y 3 0x3c 0x30 0x0b root@imx8mp-var-dart:~# i2cget -y 3 0x3c 0x40 0x56 un 0x40 sensora ID 1 Link to comment Share on other sites More sharing options...
AndrisBB Posted October 9, 2022 Author Share Posted October 9, 2022 (edited) Šodien jāpamēģina izdabūt kautkādu dzīvību ārā no tā sensora. Linux kernelī (imx8 zarā) ir kādas 5 - 6 draivera versijas priekš ov5640 sensora, bet neviena īsti nestrāda un nekādas dzīvības pazīmes neuzrāda. Sākot jau no paša sākuma. Izskatās ka visi draiveri ir rakstīti ar domu ka tiek izmantoti divi atsevišķi POWER-DOWN/RESET pini, bet PCAM 5C modulim ir tikai POWER-UP pins. static void ov5640_power(struct ov5640_dev *sensor, bool enable) { gpiod_set_value_cansleep(sensor->pwdn_gpio, enable ? 0 : 1); } static void ov5640_reset(struct ov5640_dev *sensor) { if (!sensor->reset_gpio) return; gpiod_set_value_cansleep(sensor->reset_gpio, 0); /* camera power cycle */ ov5640_power(sensor, false); usleep_range(5000, 10000); ov5640_power(sensor, true); usleep_range(5000, 10000); gpiod_set_value_cansleep(sensor->reset_gpio, 1); usleep_range(1000, 2000); gpiod_set_value_cansleep(sensor->reset_gpio, 0); usleep_range(20000, 25000); } static int ov5640_set_power_on(struct ov5640_dev *sensor) { struct i2c_client *client = sensor->i2c_client; int ret; ret = clk_prepare_enable(sensor->xclk); if (ret) { dev_err(&client->dev, "%s: failed to enable clock\n", __func__); return ret; } ret = regulator_bulk_enable(OV5640_NUM_SUPPLIES, sensor->supplies); if (ret) { dev_err(&client->dev, "%s: failed to enable regulators\n", __func__); goto xclk_off; } ov5640_reset(sensor); ov5640_power(sensor, true); ret = ov5640_init_slave_id(sensor); if (ret) goto power_off; return 0; power_off: ov5640_power(sensor, false); regulator_bulk_disable(OV5640_NUM_SUPPLIES, sensor->supplies); xclk_off: clk_disable_unprepare(sensor->xclk); return ret; } Apskatot sensora datašītu, tur ir diezgan specifiska power-up (power-down) sekvence, savādāk tur visdrīzāk nekas nedarbosies. Pietam sensoram ir POWER-DOWN pins ar 'activ low' loģiku, kamer modulim ir POWER-UP ar 'active-high' loģiku un uz moduļa divi bufferi, loģikas inverteri. Outputs no pirmā ieiet otrajā, pielikot 5.5ms aizturi. Tā pat labāk, nav jāčakarējas ar diviem piniem. Tik jāizmanto apgrieztu loģiku. Edited October 9, 2022 by AndrisBB Link to comment Share on other sites More sharing options...
AndrisBB Posted October 9, 2022 Author Share Posted October 9, 2022 (edited) Iesākumā jāpamēģina uzrakstīt bash scriptu, lai dabūtu kautkādas dzīvības pazīmes ārā no tā sensora un tad var mēģināt pielabot draiveri. GPIO paslēdzelēt vienkārši, Porta 0 vienpadsmitais pins jau eksportēts kā outputs, pieejams uz headera un brīvs, tapēc izmantošu to. root@imx8mp-var-dart:/home/weston# gpioinfo gpiochip0 gpiochip0 - 32 lines: line 0: unnamed unused input active-high line 1: unnamed unused input active-high line 2: unnamed unused input active-high line 3: unnamed "interrupt" input active-high [used] line 4: unnamed unused input active-high line 5: unnamed "hdmi_on" output active-high [used] line 6: unnamed unused input active-high line 7: unnamed "ads7846_pendown" input active-high [used] line 8: unnamed unused input active-high line 9: unnamed unused input active-high line 10: unnamed "int" input active-high [used] line 11: unnamed unused output active-high line 12: unnamed "spi0 CS1" output active-low [used] line 13: unnamed unused input active-high line 14: unnamed "interrupt" input active-high [used] line 15: unnamed "interrupt" input active-high [used] line 16: unnamed unused input active-high line 17: unnamed unused input active-high line 18: unnamed unused input active-high line 19: unnamed unused input active-high line 20: unnamed unused input active-high line 21: unnamed unused input active-high line 22: unnamed unused input active-high line 23: unnamed unused input active-high line 24: unnamed unused input active-high line 25: unnamed unused input active-high line 26: unnamed unused input active-high line 27: unnamed unused input active-high line 28: unnamed unused input active-high line 29: unnamed unused input active-high line 30: unnamed unused input active-high line 31: unnamed unused input active-high Pēctam slēdzelēt var ar gpioset gpioset gpiochip0 11=1 No kerneļa draiveriem izkopēju reģistru vērtības tīri testam, lai redzētu vai kautkas parādīsies uz CSI porta datu un pulksteņa līnijām. Bash scripts testam: #/bin/bash function read_register() { i2cset -y 3 0x3c "$1" "$2" ret=$(i2cget -y 3 0x3c) } function write_register() { i2cset -y 3 0x3c "$1" "$2" "$3" i } echo "Starting ov5640 setup ....." echo "--------------------------------------------------" echo " Hardware power toggle" echo "--------------------------------------------------" gpioset gpiochip0 11=0 usleep 100000 gpioset gpiochip0 11=1 usleep 50000 echo "--------------------------------------------------" echo " Read chip ID registers" echo "--------------------------------------------------" read_register "0x30" "0x0a" ID_HIGH=$ret echo "ID High byte:$ID_HIGH" read_register "0x30" "0x0b" ID_LOW=$ret echo "ID Low byte:$ID_LOW" if [ "$ID_HIGH" != "0x56" ] || [ "$ID_LOW" != "0x40" ]; then echo "Chip ID FAIL" exit 1 else echo "Chip ID OK" fi echo "--------------------------------------------------" echo " Init default config" echo "--------------------------------------------------" # Set clock from the input pin. Dont know why 0x11 echo "Set input clock" write_register "0x31" "0x03" "0x11" echo "Software reset" write_register "0x30" "0x08" "0x83" usleep 10000 echo "Software power down" write_register "0x30" "0x08" "0x42" echo "Set system input clock from PLL" write_register "0x31" "0x03" "0x03" echo "Set MD2P,MD2N,MCP,MCN,MD1P,MD1N pins as inputs" write_register "0x30" "0x17" "0x00" write_register "0x30" "0x18" "0x00" echo "--------------------------------------------------" echo " Setup system clock config" echo "--------------------------------------------------" # +----------------+ +------------------+ +---------------------+ +---------------------+ # XVCLK | PRE_DIV0 | | Mult (4+252) | | Sys divider (0=16) | | MIPI divider (0=16) | # +-------+-----> 3037[3:0]=0001 +--------> 3036[7:0]=0x38 +---------> 3035[7:4]=0001 +--------> 3035[3:0]=0001 | # 12MHz | | / 1 | 12MHz | * 56 | 672MHz | / 1 | 672MHz | / 1 | # | +----------------+ +------------------+ +----------+----------+ +----------+----------+ # | | | # | | MIPISCLK|672MHz # | | | # | +----------------+ +------------------+ +----------v----------+ +----------v----------+ # | | PRE_DIVSP | | R_DIV_SP | | PLL R divider | | MIPI PHY | MIPI_CLK # +-----> 303d[5:4]=01 +--------> 303d[2]=0 (+1) | | 3037[4]=1 (+1) | | +-------> # | / 1.5 | 8MHz | / 1 | | / 2 | | / 2 | 336MHz # +----------------+ +---------+--------+ +----------+----------+ +---------------------+ # | | # | | # | | # +----------------+ +---------v--------+ +----------v----------+ +---------------------+ # | SP divider | | Mult | | BIT div (MIPI 8/10) | | SCLK divider | SCLK # | 303c[3:0]=0x1 +<-------+ 303b[4:0]=0x19 | | 3034[3:0]=0x8) +----+---> 3108[1:0]=01 (2^) +-------> # | / 1 | 200MHz | * 25 | | / 2 | | | / 2 | 84MHz # +--------+-------+ +------------------+ +----------+----------+ | +---------------------+ # | | | # | | | # | | | # +--------v-------+ +----------v----------+ | +---------------------+ # | R_SELD5 div | ADCCLK | PCLK div | | | SCLK2x divider | # | 303d[1:0]=001 +-------> | 3108[5:4]=00 (2^) | +---> 3108[3:2]=00 (2^) +-------> # | / 1 | 200MHz | / 1 | | / 1 | 168MHz # +----------------+ +----------+----------+ +---------------------+ # | # | # | # +----------v----------+ +---------------------+ # | P divider (* #lanes)| PCLK | Scale divider | # | 3035[3:0]=0001 +--------> 3824[4:0] | # | / 1 | 168MHz | / 2 | # +---------------------+ +---------------------+ echo "Set PLL charge pump, MIPI 8-bit mode" write_register "0x30" "0x34" "0x18" echo "System clock divider /1, Scale divider for MIPI /1" write_register "0x30" "0x35" "0x11" echo "Set PLL multiplier x56 = 672Mhz" write_register "0x30" "0x36" "0x38" echo "PLL root divider /2, [3:0]=1 PLL pre-divider /1" write_register "0x30" "0x37" "0x11" echo "PCLK root divider /1, SCLK2x root divider /1, SCLK root divider /2" write_register "0x31" "0x08" "0x01" echo "PRE_DIV_SP /1.5, R_DIV_SP /1, DIV12_SP /1" write_register "0x30" "0x3D" "0x10" echo "PLL2 multiplier DIV_CNT5B = 25" write_register "0x30" "0x3B" "0x19" echo "--------------------------------------------------" echo " Setup other resisters (some mystery and magic values from the ov5640 Linux driver)" echo "--------------------------------------------------" write_register "0x36" "0x30" "0x2e" write_register "0x36" "0x31" "0x0e" write_register "0x36" "0x32" "0xe2" write_register "0x36" "0x33" "0x23" write_register "0x36" "0x21" "0xe0" write_register "0x37" "0x04" "0xa0" write_register "0x37" "0x03" "0x5a" write_register "0x37" "0x15" "0x78" write_register "0x37" "0x17" "0x01" write_register "0x37" "0x0b" "0x60" write_register "0x37" "0x05" "0x1a" write_register "0x39" "0x05" "0x02" write_register "0x39" "0x06" "0x10" write_register "0x39" "0x01" "0x0a" write_register "0x37" "0x31" "0x02" write_register "0x36" "0x00" "0x37" write_register "0x36" "0x01" "0x33" write_register "0x30" "0x2d" "0x60" write_register "0x36" "0x20" "0x52" write_register "0x37" "0x1b" "0x20" write_register "0x47" "0x1c" "0x50" write_register "0x3a" "0x13" "0x43" write_register "0x3a" "0x18" "0x00" write_register "0x3a" "0x19" "0xf8" write_register "0x36" "0x35" "0x13" write_register "0x36" "0x36" "0x06" write_register "0x36" "0x34" "0x44" write_register "0x36" "0x22" "0x01" write_register "0x3c" "0x01" "0x34" write_register "0x3c" "0x04" "0x28" write_register "0x3c" "0x05" "0x98" write_register "0x3c" "0x06" "0x00" write_register "0x3c" "0x07" "0x08" write_register "0x3c" "0x08" "0x00" write_register "0x3c" "0x09" "0x1c" write_register "0x3c" "0x0a" "0x9c" write_register "0x3c" "0x0b" "0x40" write_register "0x50" "0x3d" "0x00" write_register "0x38" "0x20" "0x46" write_register "0x30" "0x0e" "0x45" write_register "0x48" "0x00" "0x14" write_register "0x30" "0x2e" "0x08" write_register "0x43" "0x00" "0x30" write_register "0x43" "0x00" "0x6f" write_register "0x50" "0x1f" "0x01" write_register "0x47" "0x13" "0x03" write_register "0x44" "0x07" "0x04" write_register "0x44" "0x0e" "0x00" write_register "0x46" "0x0b" "0x35" write_register "0x46" "0x0c" "0x20" write_register "0x38" "0x24" "0x01" write_register "0x50" "0x00" "0x07" write_register "0x50" "0x01" "0x03" echo " Init Done, stay in software power-down" usleep 10000 echo "Software power up" write_register "0x30" "0x08" "0x02" # echo "--------------------------------------------------" # echo " Setup 1080P@15fps mode" # echo "--------------------------------------------------" # echo "Software power down" # write_register "0x30" "0x08" "0x42" # echo "Write mode config" Edited October 9, 2022 by AndrisBB Link to comment Share on other sites More sharing options...
AndrisBB Posted October 9, 2022 Author Share Posted October 9, 2022 (edited) I2C strādā bez problēmām un uz CSI data līnijas sāk parādīties kautkādi dati. Man Logic Analyzers tikai 200Mhz, tapēc neko vairāk par troksni tur redzēt negaidiju. Pixel cloks iet uz 336Mhz. Vajadzētu kautkādu 1Ghz Logic analaizeri, lai kautko jēdzīgu ieraudzītu. Edited October 9, 2022 by AndrisBB Link to comment Share on other sites More sharing options...
AndrisBB Posted October 9, 2022 Author Share Posted October 9, 2022 Mazliet modificējot Device Tree un ov5640 driveri, izskatās ka strādā. Pa lielam: - Definējam 'power-up' GPIO pinu iekš Device Tree pinctrl_csi1: csi1grp { fsl,pins = < MX8MP_IOMUXC_GPIO1_IO11__GPIO1_IO11 0x10 >; }; - Definējam fiksētu cloku (12Mhz oscilātors ir uz kameras moduļa) pcam_5c_osc: pcam_5c_osc { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <12000000>; }; - Pievienojam devaisu uz I2C busa, norādam iepriekš definēto pinu, cloku un datu outputu uz MIPI CSI 1 portu, ar divām datu un vienu cloka līniju. &i2c4 { clock-frequency = <400000>; pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c4>; pinctrl-1 = <&pinctrl_i2c4_gpio>; scl-gpios = <&gpio5 20 GPIO_ACTIVE_HIGH>; sda-gpios = <&gpio5 21 GPIO_ACTIVE_HIGH>; status = "okay"; ov5640_mipi1: ov5640_mipi@3c { compatible = "ovti,ov5640"; reg = <0x3c>; clocks = <&pcam_5c_osc>; clock-names = "xclk"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_csi1>; powerdown-gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>; csi_id = <1>; mipi_csi; status = "okay"; port { ov5640_mipi_1_ep: endpoint { remote-endpoint = <&mipi_csi1_ep>; data-lanes = <1 2>; clock-lanes = <0>; }; }; }; - Modificējam mazliet draiveri, lai izmanto tikai vienu GPIO, piliekam pareizu polaritāti un taimingus - Pārkompilējam Linux kerneli Link to comment Share on other sites More sharing options...
AndrisBB Posted October 9, 2022 Author Share Posted October 9, 2022 Linuksā parādās vairāki jauni video devaisi. Vajadzīgais ir /dev/video2 Atbalstāmie formāti: Spoiler root@imx8mp-var-dart:/home/weston# v4l2-ctl -d /dev/video2 --list-formats-ext ioctl: VIDIOC_ENUM_FMT Type: Video Capture Multiplanar [0]: 'RGBP' (16-bit RGB 5-6-5) Size: Discrete 176x144 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 320x240 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 640x480 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 720x480 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 720x576 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1024x768 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1280x720 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1920x1080 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) [1]: 'RGB3' (24-bit RGB 8-8-8) Size: Discrete 176x144 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 320x240 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 640x480 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 720x480 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 720x576 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1024x768 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1280x720 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1920x1080 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) [2]: 'BGR3' (24-bit BGR 8-8-8) Size: Discrete 176x144 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 320x240 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 640x480 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 720x480 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 720x576 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1024x768 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1280x720 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1920x1080 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) [3]: 'YUYV' (YUYV 4:2:2) Size: Discrete 176x144 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 320x240 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 640x480 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 720x480 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 720x576 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1024x768 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1280x720 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1920x1080 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) [4]: 'YUV4' (32-bit A/XYUV 8-8-8-8) Size: Discrete 176x144 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 320x240 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 640x480 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 720x480 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 720x576 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1024x768 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1280x720 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1920x1080 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) [5]: 'NV12' (Y/CbCr 4:2:0) Size: Discrete 176x144 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 320x240 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 640x480 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 720x480 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 720x576 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1024x768 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1280x720 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1920x1080 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) [6]: 'YM24' (Planar YUV 4:4:4 (N-C)) Size: Discrete 176x144 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 320x240 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 640x480 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 720x480 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 720x576 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1024x768 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1280x720 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1920x1080 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) [7]: 'XR24' (32-bit BGRX 8-8-8-8) Size: Discrete 176x144 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 320x240 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 640x480 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 720x480 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 720x576 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1024x768 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1280x720 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1920x1080 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) [8]: 'AR24' (32-bit BGRA 8-8-8-8) Size: Discrete 176x144 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 320x240 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 640x480 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 720x480 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 720x576 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1024x768 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1280x720 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1920x1080 Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.033s (30.000 fps) Testējam video: gst-launch-1.0 v4l2src device=/dev/video2 ! video/x-raw,width=1280,height=720,format=NV12 ! imxvideoconvert_g2d ! autovideosink sync=false 1920x1080 kautkā ne pārāk vēlas strādāt, bilde viens vienīgs troksnis. Jāuztaisa normāls konnektors, jaur tiem jumper vadiem pārāk liels troksnis visdrīzāk. Link to comment Share on other sites More sharing options...
AndrisBB Posted October 20, 2022 Author Share Posted October 20, 2022 Šodien pieliku GPS moduli. U-Blox. Tāds pats kā šis, tik vecākā izpildījumā https://store.uputronics.com/index.php?route=product/product&path=64&product_id=84 Pa lielam nekas īpaši interesants. Piespraud pie UART porta un tad startē `gpsd`, lai parsē NMEA messidžus un posto rezultātus uz d-bus. Pēctam to var integrēt applikācijā. Lai pārbaudūtu vai kāda dzīvība nāk ārā no tā moduļa, vienkārši atver seriālo portu ar `minicom` root@imx8mp-var-dart:~# minicom -D /dev/ttymxc1 -b 9600 Welcome to minicom 2.7.1 OPTIONS: I18n Compiled on Apr 18 2017, 09:55:23. Port /dev/ttymxc1, 11:01:56 Press CTRL-A Z for help on special keys $GLGSV,3,2,11,75,40,073,18,76,23,138,,80,18,336,,81,36,241,11*69 $GLGSV,3,3,11,82,38,307,31,83,11,346,,88,04,199,*5D $GNGLL,5130.20,N,00235.20,W,120310.00,A,A*64 $GNRMC,120311.00,A,5130.20,N,00235.20,W,0.094,,201022,,,A*72 $GNVTG,,T,,M,0.094,N,0.174,K,A*32 $GNGGA,120311.00,5130.20,N,00235.20,W,1,12,0.74,77.5,M,48.6,M,,*6F Pašam parsēt tos messidžus jēga maza, `gpsd` lieliski ar to tiek galā. Lai startētu izveidojam systemd servisa failu [Unit] Description=GPS (Global Positioning System) Daemon After=chronyd.service [Service] Type=forking EnvironmentFile=-/etc/default/gpsd EnvironmentFile=-/etc/sysconfig/gpsd ExecStart=/usr/sbin/gpsd $GPSD_OPTIONS $OPTIONS $DEVICES [Install] WantedBy=multi-user.target ... un defaulto configu /etc/default/gpsd.default START_DAEMON="true" GPSD_OPTIONS="-n -D 2 -s 9600" DEVICES="/dev/ttymxc1" USBAUTO="true" GPSD_SOCKET="/var/run/gpsd.sock" Rezultātus var nolasīt no d-bus vai Unix socketa, kas nu kuram labāk patīk. root@imx8mp-var-dart:~# busctl monitor ‣ Type=signal Endian=l Flags=1 Version=1 Cookie=8 Sender=:1.3 Path=/org/gpsd Interface=org.gpsd Member=fix UniqueName=:1.3 MESSAGE "didddddddddddds" { DOUBLE 1.66627e+09; INT32 3; DOUBLE 0.005; DOUBLE 51.50; DOUBLE -2.58; DOUBLE 38; DOUBLE 64.1; DOUBLE 137.77; DOUBLE nan; DOUBLE nan; DOUBLE 0.0457856; DOUBLE 46.7193; DOUBLE 0.6; DOUBLE 275.54; STRING "/dev/ttymxc1"; }; Link to comment Share on other sites More sharing options...
Artanis Posted October 20, 2022 Share Posted October 20, 2022 (edited) 24.09.2022. , 00:39, AndrisBB teica: Bet nu visa doma jau pārcelt visu uz pa taisno uz kameru, la i pēctam nav jātaisa post-edit. Par plugina daļu post-editingam būtu skaidrs, bet šo daļu no Tava sacītā gan es nesapratu - vai Tava ideja ir saķīmiķot kopā devaisu, uz kura griezt šo kodu, un ko stiprināt pa vidu starp action kameru, caur HDMI un uz portatīvo DVR? Izklausās pēc mēmās izvirtības... Vai nebūtu gadījumā vieglāk paņemt kādu no normālākajām tirgū esošajām ķiveres kamerām, kurām sensors ar plati ir savienots caur flexi (piem. MobiusCam) un ietapoties ar šo te pa vidu starp sensoru un pārējo plati? Sanāktu tieši tas, kā strādā, piemēram, tie moduļi, kas uzklāj dronu/lidmodeļu flight controller datus pa virsu FPV pārraidītajai bildei - atšķirība gan tā, ka tie visi parasti ir priekš analogā PAL/NTSC signāla, ne priekš 1080p transkodēšanas reālajā laikā. Edited October 20, 2022 by Artanis Link to comment Share on other sites More sharing options...
AndrisBB Posted October 20, 2022 Author Share Posted October 20, 2022 Pagidām doma ir izveidot pašu action cameru, kurai varēs 'piepārot' kautkādus ANT+ sensorus. Pēctam var uztaisīt glītus widgetus iekš SVG/JS, kas renderēsies reālajā laikā. Nav jau doma uztaisīt ko lietderīgu finālā, vairāk eksperimentiem, skilla trenēšanai. Nav jau tā ka tās vajadzība rodas ne no kurienes, bieži vien saistītas ar darbu tikuntā. Piemēram tā 'overleyu' problēma ir aktuāla vienā projektā, kur tieši arī ir PAL/NTSC kameras, tik "dziļā okeāna" pētīšanai/monitorēšanai. Tāpat arī doma izmantot NPU (Neural Processing Unit), kautkādam primitīvam AI, lai noteiktu trubas resnumu, kurā kamera iebāzta (trubu inspekcijas kamera), pavisam citā projektā. Link to comment Share on other sites More sharing options...
Anonīms Alkoholiķis Posted October 21, 2022 Share Posted October 21, 2022 (edited) Kur projekts ar saules paneļiem darbināmā deep learning block chainam, kas prot noteikt interneta trubas platumu? Edited October 21, 2022 by Anonīms Alkoholiķis Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now