Finally servo

This commit is contained in:
Nomi Nonsense (Nonszy) 2024-03-09 21:05:33 +07:00
parent 6d4167809b
commit 70c2fe56c8
7 changed files with 249 additions and 29 deletions

View File

@ -0,0 +1,28 @@
import { ChangeEventHandler } from "react";
interface SliderProps {
className?: string;
name?: string;
value?: number;
onChange?: ChangeEventHandler<HTMLInputElement | null>
}
export function Slider ({ className, name, value, onChange }: SliderProps) {
const percent = value ? value/10 : 0
return (
<input
className={`slider ${className}`}
style={{
background: `linear-gradient(to right, #3a3affcc ${percent}%, #3a3aff4d ${percent}%)`
}}
type="range"
min={0}
max={1000}
name={name}
value={value}
onChange={onChange}
id=""
/>
)
}

View File

@ -10,10 +10,10 @@ import Button from "../forms/Button";
function Card ({ index, resistor }: { index: number, resistor: DynamicPinState }) {
const { setResistorPin, removeResistor } = usePhotoresistor();
const [isListen, setListen] = useState(false);
const [isListen, setListen] = useState<boolean>(false);
const resistance = resistor.state;
const intensity = `${resistor.state / 1023 * 100}%`;
const resistance: number = Math.floor(resistor.state);
const intensity: number = Math.floor(100 - (resistor.state / 1023 * 100));
const toggleListen = () => {
setListen(!isListen);
@ -46,7 +46,7 @@ function Card ({ index, resistor }: { index: number, resistor: DynamicPinState }
/>
<TwoRowTab
prop="Light Intensity"
value={intensity}
value={`${intensity}%`}
/>
<EvoInput
className="h-10"

View File

@ -0,0 +1,122 @@
import { ChangeEvent, MouseEventHandler, Ref, useEffect, useState } from "react";
import { useServo } from "../../hooks";
import { DynamicPinState } from "../../types/board";
import EvoInput from "../forms/EvoInput";
import Button from "../forms/Button";
import { Slider } from "../forms/Slider";
function Bar ({ index, servo }: { index: number, servo: DynamicPinState }) {
const { setServoPin, setDegree, removeServo } = useServo();
const [percentage, setPercent] = useState(0);
const [isListen, setListen] = useState(false);
useEffect(() => {
const deg = Math.floor((percentage / 1000) * 180);
setDegree(servo.pin, deg);
}, [percentage]);
const toggleListen = () => {
setListen(!isListen);
}
const handleChange = (e: ChangeEvent<HTMLInputElement | null>) => {
const percent = Number.parseInt(e.target.value);
if (!Number.isNaN(percent)) setPercent(percent);
}
const handleChangePin = (e: ChangeEvent<HTMLInputElement | null>) => {
setServoPin(index, e.target.value);
}
const handleDelete = () => {
removeServo(index);
}
return (
<div className="border border-border bg-secondary rounded-lg p-6 animate-size-fade-in relative">
<button className="ms-auto absolute -right-24 top-1/2 -translate-y-1/2 bg-finn hover:bg-secondary transition border border-border rounded-lg px-5" onClick={handleDelete}>
<i className="bi bi-dash text-3xl"></i>
</button>
<div className="flex justify-between mb-8">
<div className="flex gap-3">
<EvoInput
name="Pin"
value={servo.pin.toString()}
onChange={handleChangePin}
type="text"
/>
{!isListen ? (
<Button.Primary onClick={toggleListen} className="text-sm !py-0 h-11">Start Listening</Button.Primary>
) : (
<Button.Danger onClick={toggleListen} className="text-sm !py-0 h-11">Stop Listening</Button.Danger>
)}
</div>
<div className="">{servo.state+"°"}</div>
</div>
<div className="">
<Slider
name={`Servo ${servo.pin}`}
value={percentage}
onChange={handleChange}
/>
</div>
</div>
)
}
function BarPlus ({ onClick }: { onClick?: MouseEventHandler<HTMLButtonElement> }) {
return (
<button
className="bg-finn h-36 hover:bg-secondary transition col-span-2 rounded-lg border border-border flex items-center justify-center"
onClick={onClick}
>
<i className="bi bi-plus text-6xl text-border"></i>
</button>
)
}
function ControlServo ({ refto }: { refto?: Ref<HTMLDivElement> }) {
const { motoServo, addServo } = useServo();
const handleAdd = (): void => {
let anopin = 5;
for (let i = 0; i < motoServo.length; i++) {
if (motoServo.filter(servo => (servo.pin == `A${anopin}` || servo.pin == anopin)).length > 0) {
anopin--;
}
else break;
}
addServo(`A${anopin}`, 0);
}
return (
<div className="container py-16" id="rgb-led" ref={refto}>
<div className="container-grid items-center relative">
<div className={`col-span-8`}>
<h2 className="text-4xl font-poppins font-bold leading-normal mb-4">
Servo
</h2>
<div className="grid grid-cols-8 mb-8">
<p className="col-span-6">Servo motors is a type of electric motor designed to provide precise motion and accurate control. Servo motors use a feedback mechanism to control their shaft position and rotational speed.</p>
</div>
<div className={`flex flex-col gap-6`}>
{motoServo.map((servo, i) => (
<Bar
key={i}
servo={servo}
index={i}
/>
))}
{motoServo.length < 6 && <BarPlus
onClick={handleAdd}
/>}
</div>
</div>
</div>
</div>
)
}
export default ControlServo;

View File

@ -46,7 +46,12 @@ const INIT_VALUES: ControllerContextProps = {
state: 127
}
],
motoServo: [],
motoServo: [
{
pin: "A0",
state: 0
}
],
photoresistor: [
{
pin: "A0",

View File

@ -58,30 +58,56 @@
@apply grid grid-cols-8 gap-6;
}
.switch {
@apply rounded-lg transition;
}
.switch > .handler {
@apply rounded-md p-[6px] transition-[margin];
}
@layer components {
.slider {
-webkit-appearance: none;
-webkit-transition: .15s;
color: #3a3affcc;
color: #3a3aff4d;
@apply appearance-none rounded-full w-full h-3 bg-primary bg-opacity-30 transition;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
@apply appearance-none transition-all rounded-full w-5 h-5 bg-primary cursor-pointer;
}
.slider::-webkit-slider-thumb:hover {
-webkit-appearance: none;
box-shadow: 0 0 0 8px #3838ff66;
}
.slider::-webkit-slider-thumb:active {
-webkit-appearance: none;
box-shadow: 0 0 0 12px #3838ff66;
@apply w-6 h-6;
}
.slider::-moz-range-thumb {
@apply w-5 h-5 bg-primary cursor-pointer;
}
.btn {
@apply px-5 py-4 transition font-roboto-mono rounded-lg
}
.btn {
@apply px-5 py-4 transition font-roboto-mono rounded-lg
}
.switch-on {
@apply border-primary bg-primary bg-opacity-40;
}
.switch-on > .handler {
@apply bg-primary ms-[50%];
}
.switch {
@apply rounded-lg transition;
}
.switch > .handler {
@apply rounded-md p-[6px] transition-[margin];
}
.switch-off {
@apply border-disabled bg-transparent;
}
.switch-off > .handler {
@apply bg-disabled ms-0;
.switch-on {
@apply border-primary bg-primary bg-opacity-40;
}
.switch-on > .handler {
@apply bg-primary ms-[50%];
}
.switch-off {
@apply border-disabled bg-transparent;
}
.switch-off > .handler {
@apply bg-disabled ms-0;
}
}

View File

@ -121,6 +121,43 @@ export function usePiezo () {
export function useServo () {
const { motoServo, setMotoServo } = useContext(BoardControllerContext);
const getServo = (pin: number | string) => {
return motoServo.find(val => val.pin == pin);
}
const addServo = (pin: number | string, state: number) => {
const newPesistor = [...motoServo, { pin, state }];
setMotoServo!(newPesistor);
}
const removeServo = (index: number) => {
const newPesistor = motoServo.filter((_servo, i) => i != index);
setMotoServo!(newPesistor);
}
const setDegree = (pin: number | string, state: number) => {
const newPiezo = motoServo.map(servo => {
if (servo.pin == pin) return { pin, state };
return servo;
})
setMotoServo!(newPiezo);
}
const setServoPin = (index: number, newPin: number | string) => {
const newPesistor = motoServo.map((servo, i) => {
if (i == index) return { pin: newPin, state: servo.state };
return servo;
})
setMotoServo!(newPesistor);
}
return { motoServo, getServo, addServo, removeServo, setDegree, setServoPin };
}
export function usePhotoresistor () {
const { photoresistor, setPhotoresistor } = useContext(BoardControllerContext);

View File

@ -11,6 +11,7 @@ import ControlNav from "../data/control-navigation.json";
import ControlRgbLed from "../components/landing/ControlRgbLed";
import ControlPiezo from "../components/landing/ControlPiezo";
import ControlPhotoresistor from "../components/landing/ControlPhotoresistor";
import ControlServo from "../components/landing/ControlServo";
function MainPage () {
const led = useRef<HTMLDivElement | null>(null);
@ -27,6 +28,7 @@ function MainPage () {
<ControlLED refto={led} />
<ControlRgbLed refto={rgbLed} />
<ControlPiezo refto={piezo} />
<ControlServo />
<ControlPhotoresistor />
</MainBody>
</>)