发动态
综合 最新发布 最新回复
图文
列表
置顶
【元器件规范共建召集令】诚邀行业专家,定义行业规范新基准
当你在电子元器件选型时,是否因参数定义模糊反复试错?当你推进研发项目时,是否因标准不统一延误进度?如今,有一个能改变行业现状、为电子产业发展注入新动能的机会 —— 加入立创商城电子元器件规范共建项目,与更多行业专家携手,打造科学、完善、权威的元器件参数规范体系!立创商城深耕电子元器件电商领域多年,深知统一精准的参数规范对行业上下游的重要性。我们正启动一项开创性工程,现面向全国电子元器件行业规范制定人、电子行业从业者、电子专业教育从业者、资深领域电子爱好者等群体招募 20-50 名细分领域专家,涵盖接口芯片、时钟和定时、射频无线、传感器等 9 大核心方向,邀你成为这场 “规范革命” 的 “执笔人”。1、你将参与的核心领域(涵盖9大方向)接口芯片USB、PCIe、CAN芯片等接口芯片的设计关注核心参数范围划定及其参数名词解释时钟和定时晶振、定时器、时钟发生器等震荡器的设计关注核心参数范围划定及其参数名词解释射频无线RF芯片、天线模块、无线收发器等无线射频相关器件的的设计关注核心参数范围划定及其参数名词解释传感器温度、压力、光电等传感器的设计关注核心参数范围划定及其参数名词解释功能模块电源管理、信号调理模块等电子模块的设计关注核心参数范围划定及其参数名词解释物联网/通信模块5G、WiFi、蓝牙模块等无线通讯模块的设计关注核心参数范围划定及其参数名词解释单片机/微控制器ST、TI、STC等单片机器件的设计关注核心参数范围划定及其参数名词解释逻辑器件和数据转换ADC/DAC、逻辑门等与信号转换和数据转换相关的设计关注核心参数范围划定及其参数名词解释显示屏器件OLED、LCD等显示屏的设计关注核心参数范围划定及其参数名词解释 2、你的角色:从技术实践者到标准制定者评审与优化:针对公司内部团队起草的规范初稿(如参数定义、填写规范、案例模板),以专业视角审核逻辑严谨性,提出修改建议(例如隔离电压、CMTI等参数的单位换算、优先级规则);深度参与:基于实操经验,为芯片引脚定义、数据速率计算、温度范围界定等参数提供行业实践案例,确保规范兼具理论准确性与工程可行性;成果共创:与跨领域专家协作,构建类似“电子元器件维基百科”的公开规范网站,让技术标准真正服务行业生态。3、我们为你提供的四大价值回报「行业署名权」:每一份经你评审修改的规范,均将在最终版本中明确标注你的姓名与单位,成为个人技术生涯的权威背书;「品牌曝光度」:规范公开时,参与评审与编撰的专家名单将同步公示,通过公司官方渠道(行业媒体、技术社区)定向推送,提升行业影响力;「知识共享平台」:加入电子元器件规范维基网站建设,你的技术见解将被全球工程师查阅引用,成为领域内的“隐形标准制定者”;「多样激励体系」:任务制,每次任务均有丰厚报酬奖励,根据审核规范复杂度与贡献度可获取,包括且不限于京东E卡/采购晶/优惠券/实物奖励等,多劳多得激励形式:1、积分制每次任务,每人均可获得积分,根据每人贡献程度获得对应积分贡献程度人数获得积分皇冠125黄金315白银610青铜105 2、积分可兑换礼品积分数兑换礼品价值550E卡或50采购晶50元10100元E卡或100元采购晶100元20200元E卡或200元采购晶200元50500元E卡或500元采购晶500元1001000元E卡或1000元采购晶1000元2002000元E卡或2000元采购晶2000元 4、为什么工程师值得加入?技术价值升华:从“用标准”到“定标准”,让你的经验成为行业参照坐标; 资源链接机遇:与芯片原厂、方案商专家深度交流,拓展技术人脉圈; 职业发展加分:参与行业级规范制定的经历,是技术管理岗晋升的硬核背书。5、报名方式如果您在上述领域拥有多年以上研发/设计经验,或主导过元器件选型与参数验证项目,欢迎将个人简历(附技术专长说明)发送至:,邮件主题注明“【规范专家报名】+领域方向”。我们将在3个工作日内与您联系,共商规范共建蓝图。 电子元器件的每一个参数,都承载着工程师的智慧。现在,你就有机会成为定义行业规范的 “少数派”,让全球工程师使用你参与制定的标准。这不仅是一次技术实践,更是一段能为行业留下深刻印记、为职业增添高光的宝贵经历。立创商城期待与你携手,重塑元器件参数规范行业标杆,让你的技术印记,刻进行业未来! 注:“本次共建采用灵活协作模式,单次任务预计耗时2~4小时,全程线上进行,不影响日常工作。”
【元器件规范共建召集令】诚邀行业专家,定义行业规范新基准
立创商城
上期我们利用FFImageLoad实现了图片流的显示,之前也有一期简单介绍了一下利用SkiaSharp实现绘图。 本期我们来实现一个摇杆的实现。public class DrawAble {     private readonly Rocker view; public DrawAble(Rocker view) {         this.view = view; } private void Draw_Circle(SKSurface surface, SKRect bounds) { float centerX = bounds.MidX; float centerY = bounds.MidY; Midx = centerX; Midy = centerY; // 计算圆的半径(使用ChargingRingDrawable类中的rad属性) float radius = CirCleRad; // 使用SKPaint对象定义圆的样式(颜色、线条宽度等) using (SKPaint paint = new SKPaint()) { paint.Color = SKColors.Blue; paint.Style = SKPaintStyle.Stroke; paint.StrokeWidth = 20; // 画圆 surface.Canvas.DrawCircle(centerX, centerY, radius, paint); }     } public void Draw(SKSurface surface, SKRect bounds) { surface.Canvas.Clear();         Draw_Circle(surface, bounds);//画圆轮廓     } } 首先定义两个类,一个是画板类,他必须有最基本的Draw函数用来给Sharp实现接口。 其构造函数传入我们的Rocker类,这个类我们在下面定义。 public partial class Rocker : SKCanvasView {         private readonly DrawAble drawable; public Rocker() {             this.EnableTouchEvents = true;// this.drawable = new ChargingRingDrawable(this);         } protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { this.drawable.Draw(e.Surface, e.Info.Rect); this.InvalidateSurface(); } protected override void OnTouch(SKTouchEventArgs e) {             base.OnTouch(e);         } } } 接着定义一个类,命名为Rocker,这个类抽象自SKCanvasView(SkiaSharp的控件) 定义一个画板,构造的时候传入自身。 我们要保留两个处理函数,一个是OnPaintSurface,我们的控件刷新就会调用这个函数,还有一个是OnTouch函数,这个函数用来处理我们的触摸事件。private void Draw_Circle(SKSurface surface, SKRect bounds) {     float centerX = bounds.MidX;//获得画板中心 float centerY = bounds.MidY;     Midx = centerX;//用一个参数保存画板中心 Midy = centerY; // 计算圆的半径(使用ChargingRingDrawable类中的rad属性) float radius = CirCleRad; // 使用SKPaint对象定义圆的样式(颜色、线条宽度等) using (SKPaint paint = new SKPaint()) { paint.Color = SKColors.Blue; paint.Style = SKPaintStyle.Stroke; paint.StrokeWidth = 20; // 画圆 surface.Canvas.DrawCircle(centerX, centerY, radius, paint); } } 在DrawAble类中有这样子一个函数,其作用是画一个基本的圆,我设置的大小是400像素。private void Draw_InsertCircle(SKCanvas canvas, SKPoint touchLocation, float radius) { // 控件的中心点 float centerX = Midx; float centerY = Midy; // 计算手的位置与圆的交点 SKPoint intersectionPoint = CalculateIntersectionPoint(centerX, centerY, 300, touchLocation); // 使用SKPaint对象定义圆的样式(颜色、线条宽度等) using (SKPaint paint = new SKPaint()) { paint.Color = SKColors.Red; paint.Style = SKPaintStyle.Fill; // 在交点位置绘制圆 canvas.DrawCircle(intersectionPoint.X, intersectionPoint.Y, radius, paint); LocationPoint = intersectionPoint; } } private SKPoint CalculateIntersectionPoint(float centerX, float centerY, float radius, SKPoint touchLocation) { // 计算手的位置与圆的交点 float dx = touchLocation.X - centerX; float dy = touchLocation.Y - centerY; float distance = (float)Math.Sqrt(dx * dx + dy * dy); // 如果距离超出阈值,将交点移动到圆上最近的点 if (distance > radius) { float scale = radius / distance; float intersectionX = centerX + dx * scale; float intersectionY = centerY + dy * scale; return new SKPoint(intersectionX, intersectionY); } // 如果距离未超出阈值,则返回手的位置作为交点 return touchLocation; } 接着画内部的摇杆内容,我们计算这个圆和控件中心的位置,设置一个阈值,保证我们画的圆在这个阈值之内,如果超过了阈值,就计算手的位置和圆的交点,再进行画圆。 实现这样子的效果。 接着,我们补全Rocker中触摸事件protected override void OnTouch(SKTouchEventArgs e) { base.OnTouch(e); switch (e.ActionType) { case SKTouchAction.Pressed: // 处理按下事件 break; case SKTouchAction.Moved: // 处理移动事件 SKPoint touchLocation = e.Location; drawable.InsertCirclePoint = touchLocation; OnPositionChanged(new SKPoint(drawable.LocationPoint.X-drawable.Midx,drawable.LocationPoint.Y-drawable.Midy)); break; case SKTouchAction.Released: SKPoint InsertCirclePoint = new SKPoint(drawable.Midx,drawable.Midy); drawable.InsertCirclePoint = InsertCirclePoint; // 使得画布无效,触发重绘 InvalidateSurface(); OnPositionChanged(new SKPoint(0,0)); break; case SKTouchAction.Cancelled: // 处理取消事件 break; } // 标记事件已处理 e.Handled = true; } 当移动时,将位置传给DrawAble中,DrawAble会根据手的位置绘制摇杆位置。 并且在放下的时候重新归位。 同时我们定义一个事件,向MainPage中传入位置信息。private void Rocker_PositionChanged(object sender, SKPoint newPosition) {    Label.Text = $"Position: ({newPosition.X}, {newPosition.Y})"; } MainPage中打印我们的位置信息。
.NET MAUI的Android WiFi图传开发(6)——利用SkiaSharp制作一个摇杆
嘉立创PCB
B站demo演示视频:我把传感器塞进网球避震器,测了一下发球速度【项目背景】网球发球训练缺乏即时量化反馈工具。现有方案(Zepp、Babolat Play等)体积大、数据维度有限,无法捕捉发力结构细节。做了一个避震器形态的传感器模块,目标是在不显著改变球拍挥重的前提下,采集发球过程中的关键力学参数。【迭代过程】V1(已废弃):- 直接用蓝牙模组内置MCU做开发,没有独立单片机- 想法是单IMU做完整动作轨迹重建- 实测结果:误差累计太大,加速度二次积分漂移无法在这个成本和体积下解决- 教训:没搞过固件就上蓝牙模组MCU开发,调试手段有限,效率极低V2(当前版本):- 砍掉了"全动作记录"需求,聚焦发球训练——单次重复动作,每次击球间可归零,回避积分漂移问题- 加了独立STM32单片机,开发调试效率大幅提升- 换了高量程陀螺仪——发球动作核心是旋转发力(内旋),陀螺仪数据能覆盖主要需求,不再依赖加速度积分【当前方案概述】MCU:STM32C011F6P6IMU:LSM6DSVTR蓝牙模组:PB-03f供电:软包锂电核心模块重量:5.2g(不含外壳,未做工程优化)算法输出指标:- 拍头速度(发球瞬间)- 掉拍头幅度- 发力速度- 手臂内旋发力占比【当前进展】V2硬件完成并验证- 算法和数据链路跑通- 与手机App的BLE通信稳定- 已完成多次球场实测验证,四项指标实时输出【下阶段目标】做工程样机,小型化、外壳优化、电池选型及充电设计。发工程样机给网球爱好者、教练、运动员测试,吸收反馈迭代产品功能。【期望交流】希望能与做过类似消费电子/穿戴设备的,有工程化经验的朋友交流。我的邮箱:nospoon@qq.com小红书(记录了开发的部分过程):there is no spoon#DIY设计#
DIY网球发球训练数据采集模块,希望能与感兴趣的朋友交流
开源硬件平台
前言如果你点的椰果奶茶被做成了珍珠奶茶,虽然也能喝,但就是完全不是你想要的,至少对于我这种有点强迫症的人。那么 JavaScript 就是这样一个 “随性” 的奶茶店老板,而 TypeScript 就是那个拿着订单反复跟你确认 “少糖少冰” 的靠谱店员,从根源上避免了 “错单” 的尴尬。用一句话来说其实就是:TypeScript 是更严谨的 JavaScript。一、有了 JavaScript 为什么还要有 TypeScript ?写 JavaScript 就像开盲盒,你永远不知道下一个变量里装的是 数字、字符串还是 薛定谔的 undefined。我统称它们为 盲盒变量。比如这段代码:let n = 1, m = 0; n = 'hello'; // 数字秒变字符串,JS 主打一个“灵活” function add(a, b) { if (typeof a === 'number' && typeof b === 'number') { return a + b; } } // 传入字符串,函数直接返回 undefined,Bug 这不就来了 console.log(add(1, '2')); 你以为你在写 “动态灵活” 的代码,其实是在给未来的自己 埋雷。比如上面这段代码,可能你知道等会要传 2个number类型,但是如果别人直接拿来Ctrl + cv 用你封装的函数,传了一个 string类型 那就坏了。直到 TypeScript 出现,让变量从 “盲盒” 变成了 “明码标价的商品”。二、弱类型:自由过了火就是混乱在上面代码中有这样一个情况:let n = 1; n = 'hello'; // 在 JavaScript里面不报错 如果你是 C++、Java或者Go的工程师,你肯定会觉得这人怕不是敲代码敲疯了吧。在C++、Java或者Golang里面这代码直接就报错了。这就是因为 JavaScript 是典型的弱类型语言,变量不需要提前声明类型,随时可以 “变身”。打印结果为 hello:你可以让数字 a 一秒变成字符串,编辑器连个警告都没有。这种 “自由” 在小项目里或许能跑,但项目一复杂,就会出现 add(1, '2') 这种隐蔽 Bug,排查起来堪比大海捞针。三、强类型:给变量上 “户口”TypeScript 作为 JavaScript 的超集,核心就是给变量加上了类型声明。首先要用 TypeScript,我们需要去下载它:npm install -g typescript # 全局安装 TypeScript tsc -v # 查看 TypeScript的版本 tsc project.ts # project 是你的文件名,编译 TypeScript文件 当编译完你会发现编译器给你编译出了一份对等的JavaScript文件:这个时候你就可以用Node.js去跑这份文件,因为 TypeScript 本身不能直接运行,需要先编译成 JavaScript 再运行。不过现在有一些工具可以简化这个过程,比如 ts-node、deno 等。我这里简要介绍下 ts-node的使用:ls package.json # 首先检查项目是否有 package.json 文件 npm init -y # 如果没有,初始化一个 npm install -g ts-node # 然后安装 ts-node npm install --save-dev ts-node # 或本地安装 # 运行 TypeScript文件 ts-node 2.ts # 全局安装时 npx ts-node 2.ts # 本地安装时 一般 TypeScript 都是在 React项目 等环境下运行,所以直接运行一个文件的比较少见,这里我们主要看 TypeScript 语法的使用和基础知识。同样的代码,在 TypeScript 里面就会报错:let a: number = 1; a = 'hello'; // 编辑器直接标红:不能将类型 “string” 分配给类型 “number” console.log(a); 细心的你很快就发现了猫腻:TypeScript 相较于 JavaScript 不同的地方就在于 TypeScript 的写法中明确标注了变量是什么类型。就比如这里 a 被明确声明为 number 类型,如果你想把它改成字符串,TypeScript 会立刻报错,把问题扼杀在编码阶段。这样就使得文件更加严谨。<<<顺便说句,技术大厂,前后端-测试机会,一线双一线城市坑位充足,感兴趣可以看看这个~四、TypeScript 数据类型全家桶在之前我写过几篇 JavaScript数据类型 的文章,那我们现在来看看 TypeScript 类型全家桶,他们并不完全一样,但还是有很高的相似度。比如这段代码:let isDone: boolean = false; // boolean类型 let count: number = 123; // number类型 let str: string = 'Trae'; // string类型 const symbol: symbol = Symbol(); // symbol类型 let obj: object = { [symbol]: 'Trae' // object类型(对象) }; let list: number[] = [1, 2, 3]; // array类型(数组) enum Color { Red, Green, // 类似于结构体 Blue } let color: Color = Color.Red; let notSure: any = 10; // any类型 notSure = '123'; // any 类型可以随便变,是 TypeScript 里的 “漏网之鱼” let value: unknown = 10; // unknown类型 value = '123'; let abc: string = 'hello'; // unknown 类型不能直接赋值给其他类型,比 any 更安全 // abc = value; // 报错 abc = notSure; // 不报错 let tuple: [number, string] = [10, 'hello']; // 元组:固定长度和类型的数组 function user1(): number { return 123; } function user2(): Function { return function fn(): number { return 123; } } // 报错 // function user2(): string { // return 123; // } function user3(): void {} // void 表示没有返回值 let u: undefined = undefined; // undefined类型 let n: null = null; // null类型 基本上都与 JavaScript 相似,可以去看我之前写的 JavaScript数据类型。从基础的 boolean、number、string,到复杂的 enum、tuple、unknown,TypeScript 让每个变量都有了明确的 “身份”。这里有一个注意的点就是 unknown 类型 和 any类型。unknown 类型不能直接赋值给其他类型,而 any 类型可以随便变,所以下次报错的时候看看,是不是这个原因。五、对象与类型:不是所有空对象都一样TypeScript 对对象的类型约束更严格:const obj: object = {}; const obj2: Object = {}; const obj3: {} = {}; // 错误 // obj.a = 1; // 编译错误 // obj3.a = 1; // 编译错误 // 正确(类型断言) (obj2 as any).a = 1; console.log(obj2); // 输出: { a: 1 } const hello = 'hello'; const a: 'hello' = 'hello'; object、Object 和 {} 看似相似,实际约束力度不同;字面量类型更是把变量锁死在特定值上,杜绝了 “意外变身”。六、类型守卫🛡️:给你的代码装上 “火眼金睛”TypeScript 的类型守卫,就像给你的代码配上了一个智能安检员,能在运行时精准识别变量类型。// 类型守卫 interface Person { name: string; age: number; sex?: unknown; // 可选属性,不是每个人都需要填写 } const person: Person = { name: 'henry', age: 18, sex: '男' // 可选属性,写不写都不会报错 }; // 举个类型守卫的例子:判断一个值是不是 Person 类型 function isPerson(value: unknown): value is Person { return ( typeof value === 'object' && value !== null && 'name' in value && 'age' in value ); } function printUserInfo(value: unknown) { if (isPerson(value)) { // 进入这个分支后,TypeScript 就知道 value 是 Person 类型了 console.log(`姓名:${value.name},年龄:${value.age}`); if (value.sex) { console.log(`性别:${value.sex}`); } } else { console.log('这不是一个合法的 Person 对象'); } } printUserInfo(person); // 输出:姓名:henry,年龄:18 printUserInfo({ name: 'lucy' }); // 输出:这不是一个合法的 Person 对象 七、类型转换与组合:灵活不代表放纵如果遇到类型不确定的场景,TypeScript 提供了类型断言来 “手动担保”:let someValue: any = '123'; let strLength = (someValue as string).length; // 写法一 let strLength2 = (someValue).length; // 写法二 还可以用 type 定义联合类型和交叉类型:type Person = string | number | boolean; const a: Person = 'hello'; const b: Person = 123; const c: Person = true; type PartialX = {x: number} type Point = PartialX & {y: number} // 交叉类型:合并多个类型 const p: Point = { x: 10, y: 20 } 八、泛型:写一次,适配所有类型泛型是 TypeScript 的 “秘密武器”,让函数和组件更通用。function identity(value: T) { return value; } identity (100); // 指定 T 为 number 类型 function identity2 (value: T, msg: U): T { console.log(msg); return value; } identity2 (100, 'hello'); // 多泛型参数 let arr: Array = [1, 2, 3]; let arr2: Array = [1, 2, 3, 'hello']; 泛型让 identity 函数既能处理数字,也能处理字符串,不用写多个重复函数,代码复用性直接拉满。结语从 JavaScript 的 “盲盒变量” 到 TypeScript 的 “精准类型”,本质是从 “靠运气写代码” 到 “靠逻辑写代码” 的转变。写的代码都不严谨,那还写什么代码呢😄。TypeScript 不是给你套枷锁,而是给你装护栏 —— 它不会限制你的创造力,只会帮你提前避开那些低级 Bug。所以,不要害怕红色的报错,而是试着去解决它。——转载自:风止何安啊
为什么要有 TypeScript?让 JS 告别 “薛定谔的 Bug”
开源硬件平台
社区数据
今日帖子
-
今日互动量
-
在线人数
-
帖子总量
-
用户总量
-
功能讨论
()
主题
打赏记录
服务时间:周一至周六 9::00-18:00 · 联系地址:中国·深圳(福田区商报路奥林匹克大厦27楼) · 媒体沟通:pr@jlc.com · 集团介绍
移动社区