Finally servo
This commit is contained in:
parent
6d4167809b
commit
70c2fe56c8
28
src/components/forms/Slider.tsx
Normal file
28
src/components/forms/Slider.tsx
Normal 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=""
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
@ -10,10 +10,10 @@ import Button from "../forms/Button";
|
|||||||
function Card ({ index, resistor }: { index: number, resistor: DynamicPinState }) {
|
function Card ({ index, resistor }: { index: number, resistor: DynamicPinState }) {
|
||||||
const { setResistorPin, removeResistor } = usePhotoresistor();
|
const { setResistorPin, removeResistor } = usePhotoresistor();
|
||||||
|
|
||||||
const [isListen, setListen] = useState(false);
|
const [isListen, setListen] = useState<boolean>(false);
|
||||||
|
|
||||||
const resistance = resistor.state;
|
const resistance: number = Math.floor(resistor.state);
|
||||||
const intensity = `${resistor.state / 1023 * 100}%`;
|
const intensity: number = Math.floor(100 - (resistor.state / 1023 * 100));
|
||||||
|
|
||||||
const toggleListen = () => {
|
const toggleListen = () => {
|
||||||
setListen(!isListen);
|
setListen(!isListen);
|
||||||
@ -46,7 +46,7 @@ function Card ({ index, resistor }: { index: number, resistor: DynamicPinState }
|
|||||||
/>
|
/>
|
||||||
<TwoRowTab
|
<TwoRowTab
|
||||||
prop="Light Intensity"
|
prop="Light Intensity"
|
||||||
value={intensity}
|
value={`${intensity}%`}
|
||||||
/>
|
/>
|
||||||
<EvoInput
|
<EvoInput
|
||||||
className="h-10"
|
className="h-10"
|
||||||
|
122
src/components/landing/ControlServo.tsx
Normal file
122
src/components/landing/ControlServo.tsx
Normal 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;
|
@ -46,7 +46,12 @@ const INIT_VALUES: ControllerContextProps = {
|
|||||||
state: 127
|
state: 127
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
motoServo: [],
|
motoServo: [
|
||||||
|
{
|
||||||
|
pin: "A0",
|
||||||
|
state: 0
|
||||||
|
}
|
||||||
|
],
|
||||||
photoresistor: [
|
photoresistor: [
|
||||||
{
|
{
|
||||||
pin: "A0",
|
pin: "A0",
|
||||||
|
@ -58,6 +58,37 @@
|
|||||||
@apply grid grid-cols-8 gap-6;
|
@apply grid grid-cols-8 gap-6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.switch {
|
.switch {
|
||||||
@apply rounded-lg transition;
|
@apply rounded-lg transition;
|
||||||
@ -66,12 +97,6 @@
|
|||||||
@apply rounded-md p-[6px] transition-[margin];
|
@apply rounded-md p-[6px] transition-[margin];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
@apply px-5 py-4 transition font-roboto-mono rounded-lg
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.switch-on {
|
.switch-on {
|
||||||
@apply border-primary bg-primary bg-opacity-40;
|
@apply border-primary bg-primary bg-opacity-40;
|
||||||
}
|
}
|
||||||
@ -85,3 +110,4 @@
|
|||||||
.switch-off > .handler {
|
.switch-off > .handler {
|
||||||
@apply bg-disabled ms-0;
|
@apply bg-disabled ms-0;
|
||||||
}
|
}
|
||||||
|
}
|
@ -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 () {
|
export function usePhotoresistor () {
|
||||||
const { photoresistor, setPhotoresistor } = useContext(BoardControllerContext);
|
const { photoresistor, setPhotoresistor } = useContext(BoardControllerContext);
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import ControlNav from "../data/control-navigation.json";
|
|||||||
import ControlRgbLed from "../components/landing/ControlRgbLed";
|
import ControlRgbLed from "../components/landing/ControlRgbLed";
|
||||||
import ControlPiezo from "../components/landing/ControlPiezo";
|
import ControlPiezo from "../components/landing/ControlPiezo";
|
||||||
import ControlPhotoresistor from "../components/landing/ControlPhotoresistor";
|
import ControlPhotoresistor from "../components/landing/ControlPhotoresistor";
|
||||||
|
import ControlServo from "../components/landing/ControlServo";
|
||||||
|
|
||||||
function MainPage () {
|
function MainPage () {
|
||||||
const led = useRef<HTMLDivElement | null>(null);
|
const led = useRef<HTMLDivElement | null>(null);
|
||||||
@ -27,6 +28,7 @@ function MainPage () {
|
|||||||
<ControlLED refto={led} />
|
<ControlLED refto={led} />
|
||||||
<ControlRgbLed refto={rgbLed} />
|
<ControlRgbLed refto={rgbLed} />
|
||||||
<ControlPiezo refto={piezo} />
|
<ControlPiezo refto={piezo} />
|
||||||
|
<ControlServo />
|
||||||
<ControlPhotoresistor />
|
<ControlPhotoresistor />
|
||||||
</MainBody>
|
</MainBody>
|
||||||
</>)
|
</>)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user